Find the largest square fits a rectangle

填充矩形算法
本文介绍了一种使用n个正方形填充已知宽高的矩形的算法,并确保浪费的空间最小化。通过调整正方形的大小(可以为实数),使得一条边完全被填充,而另一条边尽可能地减少剩余空间。

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;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值