给定一个画布,让我们说10x10,并给出3个矩形/正方形。
Canvas = 10x10
矩形1 = 2x2 矩形2 = 3x3 矩形3 = 2x4
我已经创建了一个递归函数来循环画布上每个矩形的每个位置,并且它工作正常。 (我已经包含了以下功能,任何人都希望看到它,但我认为没有必要)。
我们可以看到矩形1和2是不可旋转的IE,如果你将它们中的任何一个旋转90度,它们基本上是相同的形状。但矩形3是可旋转的。
如何更改/构造loop / recurisve函数,使其循环每个矩形的每个位置,以及每次可能的旋转?
目的是遍历画布上每个可能的形状拟合。
感谢您的帮助!
Sub recurse(ByVal startPoint As Integer)
Dim x As Integer
Dim y As Integer
Dim validSolution As Boolean = isSolutionValid()
Dim loopXTo As Integer
Dim loopYTo As Integer
Dim solutionRating As Integer
'If parent nodes create invalid solution, we can skip (375 iterations from 1,600 iterations saving)
If validSolution = True Then
If (startPoint = 0) Then
loopXTo = Math.Floor((canvasCols - squareObjects(startPoint).sqRows()) / 2) '576 iterations from 1,680 iterations
loopYTo = Math.Floor((canvasRows - squareObjects(startPoint).sqCols) / 2) '31,104 iterations from 90,720 iterations
Else
loopXTo = canvasCols - squareObjects(startPoint).sqRows
loopYTo = canvasRows - squareObjects(startPoint).sqCols
End If
'Loop all positions on canvas
For x = 0 To loopXTo
For y = 0 To loopYTo
'Set coords of square
squareObjects(startPoint).setSquareCords(x, y)
'Phyiscally place it in canvas
placeSquareOnCanvas(x, y, squareObjects(startPoint).sqRows, squareObjects(startPoint).sqCols)
'Recursive, get next square
If (startPoint + 1 < totalSquares) Then
recurse(startPoint + 1)
Else
validSolution = isSolutionValid()
'Is solution valud
If (validSolution = True) Then
solutions = solutions + 1
End If
iterations = iterations + 1
'Response.Write("<br /><b>Iteration " & iterations & "</b>")
If (validSolution) Then
'Rate solution, record if best
solutionRating = rateSolution()
If solutionRating > bestCellSaving Then
bestCellSaving = solutionRating
copySolution()
End If
'Response.Write(" <span style='color:green'> <B>VALID SOLUTION</B></span> (" & rateSolution() & ")")
End If
'printCanvas(canvas)
End If
squareObjects(startPoint).removeSquare(canvas)
Next
Next
End If
End Sub
答案 0 :(得分:0)
如果画布总是正方形,那么你不需要改变太多。旋转矩形3的结果与未旋转的矩形相同,只是Canvas的原点不同。想象一下,让Rectangle 3不旋转,将画布向另一个方向旋转90度。这意味着您应该能够对相同的结果使用一些数学来得到答案。
答案 1 :(得分:0)
将(x,y)坐标循环放在自己的函数中。然后在WxH的矩形上调用(x,y)坐标循环,然后在旋转的矩形HxW上再次调用它。
或者,您可以在拾取了两个坐标之后,但在进行递归调用之前,将分支放在(x,y)循环内的矩形的两个旋转上。
在这两种情况下,您都需要注意旋转是否会导致矩形超出边界框的高度或宽度。
答案 2 :(得分:0)
你不能简单地扫描形状列表,对于那些矩形(SizeX != SizeY
),用{ SizeX = source.SizeY, SizeY = source.SizeX }
添加一个克隆的矩形(例如:旋转的矩形)?
这当然意味着要做两次循环(一个用于未旋转的形状列表,一个用于旋转的一个)。
=&GT;做像
这样的事情squareObjects(startPoint) = squareObjects(startPoint).Rotate();
recurse(startPoint);
答案 3 :(得分:0)
如果在单独的例程中提取循环,则解决方案相对容易出现。
我已经更改了validSolution逻辑以使代码更短 - 现在我们不会在解决方案无效时调用recurse并且我们不需要在recurse()开头检查isSolutionValid()。这些更改使迭代计数更加困难,因此我删除了该代码,但应该可以稍后添加它。
没有最后一个“If”语句的recurse()例程应该与您的代码完全一样。最后一个“If”语句基本上执行旋转矩形的循环。
我不确定如何实现removeSquare(),但可能需要知道方向才能正常工作。
Sub recurse(ByVal startPoint As Integer)
Dim loopXTo As Integer
Dim loopYTo As Integer
If (startPoint = 0) Then
loopXTo = Math.Floor((canvasCols - squareObjects(startPoint).sqRows) / 2)
loopYTo = Math.Floor((canvasRows - squareObjects(startPoint).sqCols) / 2)
Else
loopXTo = canvasCols - squareObjects(startPoint).sqRows
loopYTo = canvasRows - squareObjects(startPoint).sqCols
End If
fitSqare(loopXTo, loopYTo, False)
If (squareObjects(startPoint).sqCols <> squareObjects(startPoint).sqRows) Then
fitSqare(loopYTo, loopXTo, True)
End If
End Sub
Sub fitSquare(ByVal loopXTo As Integer, ByVal loopYTo As Integer, ByVal rotate As Boolean)
Dim x As Integer
Dim y As Integer
Dim solutionRating As Integer
Dim validSolution As Boolean
'Loop all positions on canvas
For x = 0 To loopXTo
For y = 0 To loopYTo
'Set coords of square
squareObjects(startPoint).setSquareCords(x, y)
'Phyiscally place it in canvas
If (rotate) Then
placeSquareOnCanvas(x, y, squareObjects(startPoint).sqCols, squareObjects(startPoint).sqRows)
Else
placeSquareOnCanvas(x, y, squareObjects(startPoint).sqRows, squareObjects(startPoint).sqCols)
End If
validSolution = isSolutionValid()
'Is solution valud
If (validSolution) Then
'Recursive, get next square
If (startPoint + 1 < totalSquares) Then
recurse(startPoint + 1)
Else
solutions = solutions + 1
'Rate solution, record if best
solutionRating = rateSolution()
If solutionRating > bestCellSaving Then
bestCellSaving = solutionRating
copySolution()
End If
End If
End If
squareObjects(startPoint).removeSquare(canvas) 'removeSquare may require additional work to handle rotated state
Next
Next
End Sub
答案 4 :(得分:0)
坦率地说,我不认为你的实现是最好的 - 但是如果你不想进行大的改动并制作单独的例程,你可以在相同的函数迭代中将矩形的代码放两次。
所以之后:
'Phyiscally place it in canvas
placeSquareOnCanvas(x, y, squareObjects(startPoint).sqRows, squareObjects(startPoint).sqCols)
[......]
End If
squareObjects(startPoint).removeSquare(canvas)
[......]
您可以进行检查
如果正方形是矩形(宽度&lt;&gt;高度) 然后再次复制相同的代码(在Then代码中),在placeSquareOnCanvas()中使用sqCols更改sqRows。
递归将不再是线性的,因为这将为每个矩形制作2个递归分支。也许写两次相同的代码写不是很好,但结果是正确的,代码更改是最小的,基于代码的这个直接解决方案将比尝试其他调整具有更多的性能。