最大化放置在圆中的矩形所利用的面积。

4
我有一个圆形,需要用矩形填充。这些矩形只有特定的尺寸可用,并且指定了我们必须放置的矩形数量。 我需要获取涵盖圆形最大面积的一组矩形长度。例如,如果圆的直径为100,则可以放置长度为[100, 95, 90, 85,... 15,10,5]的矩形。我已经尝试使用暴力方法通过遍历所有可能的组合来实现。 当数字较小时,它会产生良好的结果。我尝试过的另一种算法是限制每个矩形占用的长度范围。例如第一个矩形的长度为95或90以达到最佳结果。但是当要放置的矩形数量非常大时,即使这种方法也很麻烦。以下是矩形的排列方式: enter image description here 如果第一个矩形的长度为l,圆的直径为d,则其厚度为sqrt(d2-l2)。 如果第二个矩形的长度为k,则其厚度为sqrt(d2-k2)-sqrt(d2-l2)。
是否有任何算法可以让我制定结果?

3
这个问题对我来说并不明确。你的例子似乎表明矩形的某些部分可以超出圆圈,是这样吗?矩形的高度是否受到限制?你提到有固定数量的矩形,但我在你的例子中没有看到。 - Vincent van der Weele
只是为了明确一下。1. “d2”是指d²(d的平方)吗?............... 2. “第一个”矩形是什么?长度为100的矩形将具有高度(厚度)= sqrt(d²-100²)?而长度为95的第二个矩形将具有sqrt(d2-95²)-sqrt(d2-100²)? - michal.ciurus
是的,d2代表d的平方。每个矩形的厚度都是根据其宽度和前一个矩形的厚度计算出来的。你完全正确。 - Tyranicangel
1
我已经回答了一个问题(可能对您没有帮助),但我认为这个问题不适合在这里提问。最好去http://math.stackexchange.com/问。 - Tobias Knauss
由于这是一个圆形,如果您可以解决四分之一的问题,那么您可以将其镜像成为完整的解决方案。 - Khaled.K
显示剩余3条评论
4个回答

0

为什么这个问题的暴力攻击会很困难?你只需要在计算代码中付出一些努力,我相信它会正常工作。最多只有19个级别。这不应该太复杂,并且将在...嗯,几个小时内给出结果,就像我刚刚发现的那样。19个级别将导致3.3e17次计算。

关于算法:
使用一个矩形时,当矩形是正方形时,可以获得最大的覆盖面积。我认为这非常容易理解。正方形的角位于圆心的45°处(假设水平为0°,但实际上整个结构都是点对称的),大小为(0.707*直径)^2 = 5000
最接近宽度70.7的是70。通常建议检查精确结果(70.7)下面(70)和上面(75)的数字。您的矩形的面积为70 * 71.41 = 4999。(但是如果高度也必须是5格网格之一的值,那就太好了!

现在变得更困难了,希望我是对的:
当我写这个答案时,事实证明,我是不对的。:-( 四舍五入的值比理论最大值要高。但我会发表它,也许有助于找到真正的答案。

当您有两个矩形时,应该覆盖的最大区域是

  • rect1的角落在30°(和150°、210°、330°),
  • rect2的角落在60°(和120°、240°、300°)。

尺寸应为:

  • rect 1:0.866*dia * 0.5 *dia = 4330
  • rect 2:0.5 *dia * 0.866*dia = 4330- 减去重叠部分 =>> 0.5*0.36*dia^2 = 1830
  • 总和:6160

四舍五入到5的网格:

  • 矩形1,#1)85*52.86 = 4478
  • 矩形2:#1)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

  • 矩形1,#2)90*43.59 = 3923

  • 矩形2:#1)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。

由于使用了圆整值,您必须检查每个矩形的上下(如果在网格上则精确)值的每个组合,导致最多进行3^n次检查,其中n是矩形的数量(除n=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 两个矩形的公式为:
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 个偏导数。祝您玩得开心!(或者考虑使用暴力法,因为您已经拥有一个网格,无需进行迭代;-))

我目前正在使用暴力破解法。当我处理一个半径为5000的圆,需要放置50个矩形时,暴力破解法会失败,因为它需要大量的时间。我需要一些计算算法来执行这个任务。我以100个圆直径作为示例来展示这个问题。 - Tyranicangel
我知道我的答案不是100%正确的,但我仍然认为它非常接近。将其与+-n步的邻居搜索相结合,应该会给您一个很好(甚至是精确)的结果。我肯定会尝试一下。顺便说一句:计算如何用50个矩形填充圆形将需要一些CPU时间,除非您找到了没有或少量迭代的完美算法,我真的不知道是否存在这样的算法。 - Tobias Knauss
我尝试了一种方法,使用牛顿-拉普森方法得到每个步骤所需的最佳结果因子。然后我检查这些因子的上限和下限。但即使如此,我仍然无法获得最佳输出。此外,当涉及到50个矩形时,我必须遍历2^50种组合。 - Tyranicangel
这个过程是模拟的一部分,其中用户运行了大约500万次迭代,如果在每次迭代中运行更多的2的50次方组合,那将会耗费大量时间。我正在寻找某种算法,以便可以大大限制组合数。 - Tyranicangel

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。
可以添加进一步的代码来记住达到最大值的值。


我不能使用暴力破解,因为当圆的直径和需要放置的矩形数量很大时,所需时间非常长。 - Tyranicangel
你可以使用暴力枚举和我的另一个答案的结合。其中的暴力枚举部分将会是通过一种近似算法进行迭代。 - Tobias Knauss

0

我再次阅读了您的问题,并意识到我在您的帖子中完全错过了几个关键点。图片让我感到困惑,但这并不是一个好借口。我之前在评论中提出的建议完全是个坏主意。我很抱歉,希望您没有花费太多时间研究它。如果我必须解决这个问题,这就是我会做的,对或错。

所以我一直在思考这个问题。我能想到的最好的解决方案是使用搜索算法,如A*。A*本身实现起来相当简单。我假设您已经有了计算面积的方法,这对我来说似乎是最难的部分。我有一个关于计算重叠矩形面积的想法,但这也是我没有编写可以证明我的建议是好的程序的原因。

我会有一个包含所有潜在矩形的主列表。将所有不在当前路径中的矩形的副本作为第n个放置的矩形添加到您的frontier中。这将允许您设置宽度,从而计算剩余要填充的圆的面积。继续这样做,每次从frontier中选择最低成本路径,并在探索m个节点后,您应该得到最佳拟合。其中m是您必须放置的矩形的总数。

对于成本评估,使用剩余填充空间的数量似乎是一个自然的选择。但需要注意的一点是,剩余区域会随着时间的推移而减少,因此您需要一个增加的区域。我认为将剩余区域除以剩余矩形的数量应该可以给您一个很好的成本函数,以找到在圆中留下最少面积的最低成本路径。这个听起来对我来说不错,但我相信还有其他可用的方法。

关于启发式,如果没有启发式函数,您仍然拥有最佳优先搜索,因此我预计它的性能要比盲目的蛮力技术更好。通过一个良好的启发式函数,我预计性能将显著提高。在思考什么样的启发式函数会更好时,我认为估计矩形填充圆的面积可能效果很好。例如,矩形面积的10%除以剩余放置的矩形数。由于没有预先确定的目标状态,任何估计都必须仅基于下一个矩形的面积。我们知道矩形的全部面积不会对解决方案产生贡献。每个矩形之后的大部分都是浪费空间,这就是我提出这个启发式的原因。与成本函数一样,对我来说这似乎是一个合理的想法,但如果有人能想到更好的方法,那就更好了。

网络上有各种关于A*的网站,但这个看起来写得很好。http://web.mit.edu/eranki/www/tutorials/search/

希望这能帮到你。


0

我知道设计一个可行的算法是很复杂的,但这是我想到的方法: 在给定直径的圆中,只能有一个矩形占据最大面积。

  1. 找出适合放入圆中的矩形的最大宽度和高度。有很多解决方案。例如,请参考:查找最大内接矩形。该矩形将占据最大面积的主要部分。

  2. 接下来的任务是用不同大小的矩形填充圆的剩余部分。如下图所示,找到最佳匹配的矩形。这可以通过检查圆点是否位于指定高度和宽度的矩形内来完成。

Rectangles in Circle

我再次同意这很难实现。


我相信这些矩形重叠,一个直接在另一个上面。这也是让我困惑的部分。我认为这是因为他在图片中使用了渐变。但我相信矩形1是灰色的矩形。在其上面,矩形2是紫绿色的矩形,依此类推... - Taekahn
这些矩形互不重叠,它们都是独立的矩形。 - Rahul Shukla
不是要和你争论,但问题中的第二句话是“堆叠在一起的”。 - Taekahn
同意,但您不觉得两个重叠的三角形不会“相加”它们各自的面积吗? - Rahul Shukla
我无法以这种方式放置矩形。它们必须像问题中一样一个接一个地放置。 - Tyranicangel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接