假設你有這個問題的最優算法,並放置在距離a <= d
從最後一行的下一行(S)。說它放置b
行。我們的貪心算法肯定會放置不超過b
線(因爲第一個標準是把儘可能少的),如果它把b
線將它們放置在距離c
與a <= c <= d
,因爲它然後將這些線就可能。
如果貪心算法沒有做優化算法做了什麼,它在不同的下列方式之一:
它放置在相同或更少的行得更遠。假設最佳算法在距下一步距離a'
處放置b'
行。然後這些線將在距離a+a'
處,並且總共將有b+b'
線。但貪婪算法可以通過選擇c' = (a+a') - c
將b'
行置於位移a+a'
處模擬最佳算法。由於c > a
和a' < d
,c' < d
這是合法的安置。
它將更少的線放在一起。這種情況實際上是有問題的。可能的是,這個地方k
不必要的行,如果任何放置需要至少k
線和所述最遠的那些需要更多的,並且被選擇的孔的佈置,使得(例如)它跨越的距離爲d
的倍數。
因此,貪婪算法在情況2下結果不起作用。但是,在其他情況下它確實不起作用。特別是,我們在第一種情況下的觀察是非常有用的:對於任何兩個展示位置(distance, lines)
和(distance', lines')
,如果distance >= distance'
和lines <= lines'
中,第一落點總是首選。這表明,下面的算法:
PlaceLines(start, stop)
// if we are close enough to the other edge,
// don't place any more lines.
if start + d >= stop then return ([], 0)
// see how many lines we can place at distance
// d from the last placed lines. no need to
// ever place more lines than this
nmax = min_lines_at_distance(start + d)
// see how that selection pans out by recursively
// seeing how line placement works after choosing
// nmax lines at distance d from the last lines.
optimal = PlaceLines(start + d, stop)
optimal[0] = [d] . optimal[0]
optimal[1] = nmax + optimal[1]
// we only need to try fewer lines, never more
for n = 1 to nmax do
// find the max displacement a from the last placed
// lines where we can place n lines.
a = max_distance_for_lines(start, stop, n)
if a is undefined then continue
// see how that choice pans out by placing
// the rest of the lines
candidate = PlaceLines(start + a, stop)
candidate[0] = [a] . candidate[0]
candidate[1] = n + candidate[1]
// replace the last best placement with the
// one we just tried, if it turned out to be
// better than the last
if candidate[1] < optimal[1] then
optimal = candidate
// return the best placement we found
return optimal
這可以通過記憶化通過把結果(seq, lines)
成(start, stop)
索引緩存來改善。這樣,我們就可以識別出我們何時試圖計算可能已經評估過的任務。我希望我們會遇到這種情況,無論你是否對問題實例使用粗略或精細離散化。
我沒有詳細討論如何使用max_lines_at_distance
和max_distance_for_lines
函數,但也許是關於這些函數的一個詞。
第一個告訴你在給定的位移很多線路都需要如何跨越幾何形狀。如果將幾何圖形和彩色孔像素化爲黑色,則這意味着在指定的位移處查看單元格行,並考慮連續的黑色線段,並從中確定所需的線條數。
第二告訴您,對於線的給定的候選號,從目前的位置處線的該數量可以被放置在最大距離。您可以通過告訴您可以放置該行數的最大距離或更少來使其更好。如果你使用這種改進,你可以扭轉在你迭代n
和方向:
- 如果
f(start, stop, x) = a
和y < x
,你只需要搜索最多a
,不stop
,從那時起;
- 如果
f(start, stop, x)
未定義,並且y < x
,則不需要再搜索。
注意,如果這是不可能的地方n
或更少的線start
和stop
之間的任何該功能可以是不確定的。
另請注意,您可以單獨記憶這些功能以節省重複的查找。您可以爲每一行預先計算max_lines_at_distance
並將其存儲在緩存中供以後使用。然後,max_distance_for_lines
可能是一個循環,在兩個邊界內檢查緩存。
*行必須定位在固定的時間間隔*意味着什麼?顯然,這並不意味着它們之間的距離都相同(你的例子會與此相矛盾)。是否對線條的水平寬度有要求?即什麼阻止你只在形狀中間做出很短的線條(這會給你最小的數字)? –
@NicoSchertler它意味着每一行'y mod I == 0',其中y是行的Y座標。你是對的,我在這裏錯過了一個約束,所以我添加了第四個:形狀內的每個可用點不能比'D/2'更遠。我編輯了主要問題。 目標是,如果一條線與一個洞相撞,我們希望將它放在洞的旁邊並保持其全長,而不是在中間切割。因此,最小化'N'而不是最小化線的總長度的目標。 – farbro
一般來說,I> D沒有保證的解決方案,因爲那麼平行線之間的空間可以大於D,並且它們的中點大於D/2遠離每條線 - 是否也保證I <= D? – jwimberley