分治演算法 士兵排隊(poj1723)

2021-08-10 08:23:37 字數 4421 閱讀 2705

【問題描述】 

在乙個劃分成網格的操場上,n個士兵散亂地站在網格點上。網格點由整數最表(x,y)表示。士兵可以沿著網格邊上、下、左、右移動一步,但在同一時刻乙個網格上只能有一名士兵。按照軍官的命令,士兵們要整齊地列成乙個水平佇列,即排列成(x,y),(x+1,y),…,(x+n-1,y)。如何選擇x,y的值,才能使士兵們以最少的總移動步數排成一列。 

請計算使所有士兵排成一行需要的最少移動步數。

【輸入格式】 

第1行是士兵總數n。接下來的n行是士兵的初始位置,每行兩個整數x和y。

【輸出格式】 

輸出士兵排成一行需要的最少移動步數。

【輸入樣例】

5

1 22 2

1 33 -2

3 3

【輸出樣例】

8
【資料範圍】 

1<=n<=10000 

-10000<=x,y<=10000

問題分析:

通過適當的移動順序和移動路線可以使得同一時刻不會有兩名士兵站在同一點。

題目要求移動的最少步數

題目要求可轉化為求士兵站立的「最終位置」,即如何取「最終位置」使得士兵移動的步數最少

1. y軸方向上的考慮(找出y0的值)

設目標座標為y0,即n個士兵最終需要移動到的y軸的座標值為m

n個士兵的y軸座標分別為:

y1,y2 …… …… yn

移動步數

s=|y1-y0|+|y2-y0|+ …… …… +|yn-y0|

結論:y0取所有yi的中間值時可以使得s達到最小。

(可以證明)

中位數是y0;

解決辦法

1.對所有的y軸座標進行排序(onlogn))或者進行線性時間選擇(on))然後取中間點的y軸座標值作為最佳位置y0的值

2.通過公式求出y軸方向上移動的最優步數

2. x軸方向上的考慮

1首先需要對所有士兵的x軸座標值進行排序

2然後,按從左至右的順序依次移動到每個士兵所對應的最終位置(最優),所移動的步數總和就是x軸方向上需要移動的步數

設排序後n個士兵在x軸座標為:

x1』x2』 …… …… xn』

他們最終位置x軸座標值為:

x0x0+1x0+2 …… …… x0+n-1

則所求移動的步數

s=|x1』-x0| + |x2』-(x0+1)|+ …… +|xn』-(x0+(n-1)|

經過變形

s=|x1』-x0|+ |(x2』-1)-x0|+ …… +|(xn』-(n-1))-x0|

注意到公式的形式與y軸方向上的考慮一樣,同樣是n個已知數分別減去乙個待定數後取絕對值,然後求和

問題轉化為:

求出x1』,x2』-1,…xn』-(n-1)的中位數,即求得x0值,最後算出最優解。

中位數尋找的快速演算法

一般尋找中位數可以先將陣列排序,按照次序將中間的資料作為中位數即可,其時間複雜度主要取決於排序演算法的時間複雜度,利用快速排序可以將其控制為線性對數量級。 

但是能否打破線性對數的限制呢?其中最關鍵的問題是,尋找中位數並不需要整個陣列完全有序,如果把多餘的元素排序省略掉,那麼就可以超越線性對數的限制實現最快的演算法。 

啟發**於快速排序演算法中的切分法,比如我們需要找到陣列中第

k小的元素,首先將陣列

a[lo,hi]

切分返回整數

j,使得

a[lo,j-1]

都小於等於

a[j]

,而a[j+1,hi]

都大於等於

a[j]

,如果j==k

,那麼j

位置的元素就是我們要找的第

k小的元素,而如果

j>k

,就要切分左子陣列,如果

j,就要切分右子陣列,不斷縮小選定的子陣列的規模直到只剩下乙個元素,則它就是最終我們要找的第

k小的元素。 

經過數學推導,這種快速切分法尋找中位數僅僅為線性量級,是尋找中位數最為快速的演算法。

int partition(int *a, int low, int high)

//分治演算法中的分

else if(j > k)

else if(j < k)

}return a[k];

} // 找出陣列中第

int select2(int a, int k, int lo, int hi) else if (j > k) else

}int main()

; cout<

這是沒用上面的找中位數的方法寫的,在poj上能過,不過時間稍稍有點長;

#include #include #include #include #include #define num 10001

using namespace std;

int com(const void *a,const void *b)

int main() //輸入操作

//士兵移動x座標或者是y座標移動乙個單位,在poj上提交可以不用這個功能;

for( int i = 0 ; i

poj 1723 求中位數(讓士兵站成一排)

題意 有n個士兵,每個士兵站的位置用乙個座標 x,y 表示,現在要將n個士兵站在同乙個水平線,即所有士兵的y座標相同並且x座標相鄰,每個士兵每次可以向相鄰位置移動一步。求最少的移動步數。思路 先把他們按照橫座標相鄰排好。我們先把橫座標排序,並假設起點是a,那麼我們就是要求i 0 n 1,abs a ...

分治法 士兵排隊問題

在乙個劃分成網格的操場上,n個士兵散亂地站在網格點上。網格點用整數座標 x,y 表示。士兵們可以沿網格邊往上 下 左 右移動一步,但在同一時刻任一網格點上只能有一名士兵。按照軍官的命令,士兵們要整齊地列成乙個水平佇列,即排列成 x,y x 1,y x n 1,y 如何選擇x和y的值才能使士兵們以最少...

藍橋杯 演算法提高 士兵排隊問題

試題 有 個士兵 1 26 編號依次為 佇列訓練時,指揮官要把一些士兵從高到矮一次排成一行,但現在指揮官不能直接獲得每個人的身高資訊,只能獲得 p1比p2高 這樣的比較結果 p1 p2 記為 p1 p2 如 表示 比 高。請編一程式,根據所得到的比較結果求出一種符合條件的排隊方案。注 比較結果中沒有...