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

被折叠的 条评论
为什么被折叠?



