Find the largest square fits a rectangle

Given a rectangle with known width and height, design an algorithms to fill 
the rectangle using n squares(n is integer, also given) and make sure in the 
result the wasting area is minimized. Length of square doesn't have to be integer.

I.e, given width=3,height=2,n=5, one solution is that rectangle can 
be filled with five 1x1 squares and the wasting area is 1. Another 
solution could be filled with five 0.9x0.9 squares, but the wasting area is more than first solution.


边长可以为实数型数字,所以不能从边上考虑。从矩形的边上容纳多少个正方形方面入手。

可以想象长边放了a个正方形,还剩余y的长度,短边放了b个正方形,还剩余x的长度。可以证明,如果让剩余空间最小,则最多只能有一条边有剩余,其他边都被填满。


如果 x/b > y/a ,正方形的边都增大y/a,对于长边而言,已经填满,对于短边而言,x>y*b/a, 还有剩余

如果 x/b < y/a , 正方形的边都增大x/b, 恰好填满短边,而长边而言,x*a/b <y ,所以长边还有剩余


所以可以先假设正方形可以填满行,再假设正方形可以填满列

边上可以放下的正方形的个数从1可以到n遍历。


可以用二分查找进行优化


bool fits(float l, float w, int m, int n)
{
        assert(l>0 && w>=0 && m>0 && n>0);

        if (n <= m && w >= l/m)
                return true;

        if (w < l/m) return false;

        return fits(l, w-l/m, m, n-m);
}

float CalcLen(int l, int w, int n)
{
        assert(l>0 && w>0 && n>0);

        int nLow = 1;
        int nHigh = n;
        int nBest = -1;

        while (nLow < nHigh)//二分有些问题
        {
                int nMid = (nLow + nHigh)/2;
                if (fits(l, w, nMid, n))
                {
                        nHigh = nMid-1;
                        nBest = nMid;
                }
                else
                        nLow = nMid+1;
        }

        if (nLow == nHigh && fits(l, w, nLow, n))
                nBest = nLow;

        return (float)l/(float)nBest;
}

float GetLargest(int l, int w, int n)
{
        assert(l>0 && w>0 && n>0);

        float r1 = CalcLen(l, w, n);
        float r2 = CalcLen(w, l, n);

        return r1>r2?r1:r2;
}


你可能感兴趣的:(Find the largest square fits a rectangle)