醉鬼同時移動問題的思路

2021-09-28 16:30:18 字數 1156 閱讀 7551

今天有學生問了乙個有趣的演算法題目:

數軸上有n個位置不同的點,各點橫座標已知,分別代表n個醉鬼的位置,每個醉鬼可以向左或者向右水平移動s個距離(不允許原地不動),問所有的人都移動一次後,隊伍的最短長度為多少(隊伍的長度定義為最右邊的人到最左邊的人的距離).

在中找到了同樣的題目,

1.問題等價於

先把整個隊伍左移s個單位,那麼現在每個人的合法操作就是原地不動(對應原問題中的左移s)或者向右移動2s(對應原問題的右移s操作).

2.現在問題轉化成n個不同位置的人,v[i]為第i個人的座標,每人可以原地不動或者向右移動m=2*s個單位,

求移動之後的隊伍最小長度.為了討論方便,我們假定第乙個人的座標為0.最後乙個人的座標為right

3.現在考慮新隊伍的所有可能性

如果第2個人向右移動的話,則它右移動之後的新位置肯定不可能是新隊伍的開頭,

因為此時第1個人無論是否移動都必然還在第2個人的左邊,

類似的第3個人到最後乙個人都不可能經過右移成為新隊伍的開頭,

但是第乙個人向右移動之後的位置有可能成為新隊伍的開頭

(相當於第1個人和第2人之間離的比較遠,第乙個人右移m之後仍然在第2個人的左邊).

所以新隊伍的開頭只有可能是

第乙個人右移之後的位置,或者第2個人到第n個人的原始位置.

4.下面的任務就是得到考慮候選解,

設第乙個人的座標為0,最後乙個人的原始座標為right.

(1)如果第1個人保持不動,則其他人也要原地不動才有可能得到最優解.即整個隊伍的原始長度為乙個候選解

(2)因為第乙個人移動之後的座標為m,則這個座標也是所有新佇列的左邊界的上限.

依次檢查第2到第n個點的原始位置是否可以成為新佇列的起點,

檢查的條件就是v[i]<= m,此時新佇列的尾部座標為end=max(right,v[i-1]+m), 這裡要考慮到左邊的人移動之後會越過原來的右邊界的情形.

然後這個新對列的長度為end-v[i].

最後還要考慮第1個點移動m之後成為新的左邊界的情況,此時的右邊界就有可能是離m最近的前乙個點平移之後的位置,

比如節點1移動m之後落到了原來的4和5之間,那麼此時

節點2到4都要右移,佇列的終點為end=max(right,v[4]+m).新佇列長度為end-(v[1]+m)

5.從以上所有候選解中找出乙個最小值即可.

陣列的移動問題

include include void left move array int a,int size 陣列向左移一位 a size 1 temp 首元素置於陣列末尾 return void right move array int a,int size 陣列向右移一位 a 0 temp 末尾元素置...

陣列移動問題

includevoid shiftleft int pinout,int n pinout tmp void shiftright int pinout,int n pinout tmp void shiftn int pinout,int n,int shiftn else int main in...

控制項移動問題

控制項移動問題 vcl元件開發及應用 我想將文字逐漸顯示,所以在文字上加蓋了乙個shape,然後用timer使得shape.top shape.top 1 但是結果是可以使文字逐漸顯示,但是閃屏嚴重,請高手幫解決一下,謝謝 直接在canvas裡畫 要麼就用雙緩衝 也可以通過定時器來觸發作個例子給你!...