我有一个圆圈,我需要用矩形填充。一个在另一个上面。矩形只有特定尺寸。我们还给出了我们必须放置的矩形数量。我需要得到一组矩形长度覆盖圆圈的大部分区域。例如,如果圆的直径为100,可以放置长度为[100,95,90,85,... 15,10,5]的矩形。我试过通过解析所有可能的组合使用强力方法。当数字较小时,它会产生良好的结果。我尝试的另一种算法是限制每个矩形占据的长度范围。就像第一个矩形的长度为95或者但是,当要放置的矩形数量非常高时,即使这种方法也很麻烦。这就是矩形的排列方式
如果第一个矩形的长度为l,圆的直径为d,则其厚度为sqrt(d2-l2)。如果长度为k,则第二个矩形的厚度为sqrt(d2-k2)-sqrt(d2) -L2)。
是否有任何算法可以制定结果。
答案 0 :(得分:0)
为什么难以对这个问题进行暴力攻击?您只需要在计算代码中付出一些努力,我相信它会正常工作。它最多只有19个级别。这不应该太复杂,并且会在......我发现的几个小时内给你结果。 19个等级将导致3.3e17计算。
关于算法:
使用一个矩形,当矩形为正方形时,您将获得最大的覆盖区域。我认为这很容易理解。正方形的角与圆心成45°(假设水平为0°,但实际上并不重要,因为整个结构是点对称的),尺寸为(0.707*diameter)^2 = 5000
。
最接近宽度70.7是70.一般情况下,我建议检查下面的数字(70)和上面的(75)准确的结果(70.7)。你的矩形区域是70 * 71.41 = 4999.(但是如果高度也必须是5格的值,那就太好了!)
现在变得越来越困难,我希望我是对的:
当我写这个答案时,事实证明,我不对。 :-(舍入值的结果比理论最大值高。但我会发布它,也许它有助于找到真正的答案。
当你有2个矩形时,要覆盖的最大区域应该是
尺寸为:
0.866*dia * 0.5 *dia = 4330
0.5 *dia * 0.866*dia = 4330
- 减去重叠=>> 0.5*0.36*dia^2 = 1830
6160
四舍五入到5的网格:
85*52.86 = 4478
50*(86.60-52.86) = 1696.2
#2)55*(83.52-52.86) = 1696.1
#3)45*(89.30-52.86) = 1648
总结:6173.87 // 6173.75 // 6126
rect 1,#2)90*43.59 = 3923
50*(86.60-43.59) = 2151
#2)55*(83.52-43.59) = 2196
#3)45*(89.30-43.59) = 2057
6074 // 6119 // 5980
获胜者是组合1.1:rect1 = 85,rect2 = 50.
由于使用舍入值,您必须检查每个矩形的上部和下部(以及它是否在网格上)的每个组合,如果n是矩形的数量,则最多检查3 ^ n个检查(除了n = 1)。蛮力不是更好,但可能更容易。 (正如上面发现的那样,它可能会返回更好的结果,因为这种方法不准确)。
编辑1: 1个矩形的公式(得到一个正方形)是:
A = x * sqrt(D²-x²)
calculate the maximum using the derivative of A:
A' = D²-2x² / sqrt(D²-x²) = 0
您也可以在此处找到它:http://oregonstate.edu/instruct/mth251/cq/Stage8/Lesson/rectangle.html
2个矩形的公式为:
A = f(x,y) = x * sqrt(D²-x²) + y * [sqrt(D²-y²)-sqrt(D²-x²)]
( x = width of r1, y = width of r2 )
n个矩形的公式取决于n个未知变量。所以你需要计算n个偏导数。玩得开心! (或考虑蛮力,因为你已经给了一个网格,不需要做迭代;-))
答案 1 :(得分:0)
强力算法
计算量:
levels calculations
1 19
2 19 + 19*18 = 361
...
5 19 + 19*18 + 19*18*17 + 19*18*17*16 + 19*18*17*16*15 = 1494559
...
10 3.7e11
15 6.3e15
19 3.3e19
C#(或C ++):
double dDia = 100;
int nSizes = 20;
int nmax = 2; // number of rectangles
int main()
{
int n = 1;
double dArea = 0.0;
dArea = CalcMaxArea (n, 0);
}
double CalcMaxArea (int n, double dSizeYParent)
{
double dArea = 0.0;
double dAreaMax = 0.0;
for (int iRun = nSizes-n; iRun >= 1; iRun--)
{
double dSizeX = iRun * 5;
double dSizeY = Math.Sqrt(dDia * dDia - dSizeX * dSizeX) - dSizeYParent);
double dAreaThis = dSizeX * dSizeY;
double dAreaOthers = 0.0;
if (n < nmax)
dAreaOthers = CalcMaxArea (n+1, dSizeY);
if (dArea > dAreaMax)
dAreaMax = dArea;
}
}
VBA,将在MS Excel中使用
Dim dDia As Double
Dim nmax As Integer
Dim nSizes As Integer
Sub main()
dDia = 100
nmax = 2
nSizes = 20
Dim n As Integer
Dim dArea As Double
n = 1
dArea = CalcMaxArea(n, 0)
End Sub
Function CalcMaxArea(n As Integer, dSizeYParent As Double) As Double
Dim dArea As Double
Dim dAreaMax As Double
dArea = 0
For iRun = nSizes - n To 1 Step -1
Dim dSizeX As Double
Dim dSizeY As Double
Dim dAreaThis As Double
Dim dAreaOthers As Double
dSizeX = iRun * 5
dSizeY = Sqr(dDia * dDia - dSizeX * dSizeX) - dSizeYParent
dAreaThis = dSizeX * dSizeY
dAreaOthers = 0
If n < nmax Then
dAreaOthers = CalcMaxArea(n + 1, dSizeY)
End If
dArea = dAreaThis + dAreaOthers
If dArea > dAreaMax Then
dAreaMax = dArea
End If
Next
CalcMaxArea = dAreaMax
End Function
使用给定值在VBA中测试,得到相同的结果:6173.87 可以添加更多代码以记住达到最大值的值。
答案 2 :(得分:0)
我再次阅读了这个问题,并意识到我完全错过了你帖子中的几个关键点。这张照片让我感到困惑,但这并不是一个好借口。我在评论中的先前建议是一个完全糟糕的主意。对不起,我希望你没有花很多时间研究它。如果我必须解决这个问题,我就是这样做的,无论是对还是错。
所以我一直在考虑这个问题。我能想到的最好的解决方案是使用搜索算法,如A *。 A *它自己很容易实现。我假设你已经有了计算面积的方法,对我来说这似乎是最难的部分。我知道如何继续计算重叠矩形的面积,但这就是为什么我没有编写一个可以证明我的建议是好的程序的原因。
我要做的是拥有所有潜在矩形的主列表。 添加到您的边界的所有矩形的副本不在当前路径中作为第n个矩形放置。这将允许您设置宽度,因此计算要填充的圆的面积。保持这样做,每次从边界选择最低成本路径,并且在探索m个节点之后,您应该最合适。其中m是您必须放置的矩形总数。
对于成本评估,使用剩余的空间量似乎是一个自然的选择。但值得注意的一点是,随着时间的推移,剩下的区域会减少,你需要增加一个区域。我认为将剩下的区域除以剩下的矩形数量应该会给你一个很好的成本函数,用于找到到圆圈中剩余最小区域的最低成本路径。那个人对我来说听起来不错,但我确信还有其他人可以使用。
关于启发式,没有启发式功能,你仍然有最好的第一次搜索,所以我希望它比盲蛮技术表现得更好。凭借良好的启发式功能,我预计性能会显着提升。在考虑什么会产生一个好的启发式功能时,我认为估计矩形填充的圆的数量可能会很好。例如,矩形区域的10%除以要放置的矩形的数量。由于没有预先确定的目标状态,因此任何估计都必须仅基于下一个矩形的区域。我们知道矩形的整个区域不会有助于解决方案。第一个之后的每个矩形的大部分是解决方案所浪费的空间,这就是我想出的启发式方法。与成本函数一样,对我来说这似乎是一个合理的想法,但如果有人能想到更好的想法,那就更好了。
A *上有各种各样的网站,但这里有一个看起来写得很好的网站。 http://web.mit.edu/eranki/www/tutorials/search/
我希望这可以帮助你。
答案 3 :(得分:0)
我知道设计一种工作算法很复杂,但这是我想到的方法: 可能只有一个矩形可以占据给定直径的圆中的最大区域。
找出可以放入圆圈的矩形的最大宽度和高度。有很多解决方案。例如,看看:Find Largest Inscribed Rectangle这个矩形将结束最大区域的主要部分。
接下来的任务是用不同大小的矩形填充圆的剩余部分。找出最合适的矩形,如下图所示。这可以通过检查圆点是否位于指定高度和宽度的矩形内来完成
我再次同意这很难实施。