2013-10-24 80 views
1

給定一個N級人(這是由數組int [] a)表示的,其中每個人都與其他人玩遊戲。每場比賽只涉及2名球員。所以對於N人來說,總共有NC2比賽。列出錦標賽中的球員,讓每名球員贏得下一場比賽?

結果與你同在所有的遊戲。你必須安排每個人排隊,條件是,a [i]應該贏得與[i-1]的比賽。這對我的所有價值都是如此。

我們不需要關心[i]和[i-2]之間的結果。 a [i]可能以[i-2]贏得或輸掉比賽。

我的做法(我用回溯來解決這個問題):

  • 對於每個人,我們將保持誰與人贏得了比賽的人的名單。
  • 將創建一個新的結果數組(長度等於總玩家數)。
  • 第一個位置被每個人迭代填滿。
  • 結果數組中的下一個位置填滿了與前一個人贏得比賽的人。通過遍歷該數組,可以從前一個人的相應獲獎名單中選出此人。

以上解決方案將嘗試每個路徑使用遞歸方法。沒有更好的算法嗎?

回答

1

這裏是一個暗示:

假設我們已經爲滿足約束的第一個I-1人的排序。是否總是有可能將某人插入到這個列表中?

考慮一下情況:任何一個人我都擊敗了所有的第一個i-1人,或者他們中的任何一個,或者其中一些人,但不是全部。在前兩種情況下,我可以插入哪些人? (這可能有助於爲目前列表中的每個i-1人分配一個1或0,表示該人是否擊敗了我)。在第三種情況下,我們可以將人i插入他們擊敗的任何人任何毆打他們的人。這樣的一對永遠存在嗎?如果沒有,我們保證能夠安全地插入我的其他任何地方嗎?

3

數學上你所擁有的東西叫做錦標賽圖,你試圖在錦標賽圖中找到哈密頓路徑。儘管在任意圖中發現哈密爾頓路徑的問題是NP難題,但已知每個比賽圖必須有哈密爾頓路徑,幸運的是他們並不難找到。

一個簡單的方法是使用遞歸。如果圖中只有一個節點,解決這個問題非常簡單:只需在圖中列出一個人即可。否則,任意選擇一個節點。將比賽分成子比賽:擊敗那個人的所有人中的一個,以及那個人失去的所有人中的一個。在每個子錦標賽中遞歸獲得哈密爾頓路徑。然後,將哈密爾頓路徑連接在一起,將第一步挑出的人放在他們之間的適當位置。

那麼這個算法效率如何?和快速排序一樣,算法的效率取決於你如何將比賽分成一小段。假設當你選擇一個人將比賽分成小塊時,你應該選擇勝利數儘可能接近n/2的人。這將產生兩個規模約爲n/2的較小比賽。決定選擇哪個人需要平方時間,因爲你必須看看每場比賽的結果來計算球員有多少勝負。這給了我們以下遞推關係:

T(N)= 2T(N/2)+ O(N )

使用主定理,我們得到了這樣的復發求解到O(n ),這比你最初的想法快得多。

希望這會有所幫助!