問題描述:給定 n (1 < n < 101) 個人,以及資訊某個人 i 是否認識 j (1<=i<=n, 1<=j<=n, i != j),你的任務是把這 n 個人分成大小近可能相近的兩隊,使得 1)每個人屬於且只屬於某一隊;2)每個隊的大小至少為 1;3)每個隊的成員都相互認識。詳見:http://acm.pku.edu.cn/judgeonline/problem?id=1112
這題不難,但題目不錯。最直接的思路是:首先建立乙個朋友網路,頂點是每乙個人,如果兩個人相互認識,則連一條邊。然後在這個圖上求兩個大小相近的完全子圖。如果做不到,則問題無解。這個思路的難點在於,一下子想不出已知的簡單的演算法來未兩個大小相近的完全子圖。至少,本人想不到現成的~
直接的反面就是間接。與其求朋友網路,不如求 「敵人」 網路:如果兩個人之間不是相互認識,則連一條邊。這樣,每條邊的兩個結點就不可能被安排到同乙個組。於是,問題就變成了乙個二部圖問題。首先,判定是不是二部圖,這個容易,廣度優先和深度優先都能做到;其次,如果是二部圖,把二部圖的兩個部分求出來,這個也很直觀了,在判定是否為二部圖可以順便做到。
直到現在為止,我們討論的只是單一連通圖的情況。這種情況下,無所謂大小相近:如果有解,解是惟一的。實際的情況是,這個「敵人」 網路可能包含有多個連通子圖。如果每個連通子圖都是二部圖,則有解。這時,就需要在每個連通子圖中選擇合適的一方來加入某個隊,從而使得兩個隊的大小相近。這時,動態規劃就派上用場了。
令 cc[1..k] 表示 k 個連線子圖,cc[i][blue|red] 表示二部圖 cc[i] 中的紅方和藍方。假定最優解的兩個隊的為數為 max 和 min,max >= min。則人數之差 d = max - min = n - 2*min。d 最小,則 min 最大,且不超 n/2。考慮這樣的揹包問題:有 k 種物品,每種物品有藍色和紅色各乙個,物品的價值 value 和重量 weight 相同,用product[i][blue | red] 表示。現在有一揹包大小為 n/2,要選 n 種不同的物品(在不同的顏色之間選一種)裝進揹包裡,並使其價值最大。顯然,這只是經典0/1 揹包問題的乙個變種。經典問題為 「選或不選」,現在問題為 「選藍色還是紅色」。把每個二部圖的藍方和紅色看成一物品,其價值和其重量為其結點個數,則求最大 min 變成了求解上述揹包問題。
1)通過輸入建立朋友網路圖
2)通過朋友網路圖求 「敵人」 網路圖
3)用 bfs 或 dfs 求解連通分支,並算出每個分支的藍方和紅方,同時判斷問題是否可解
4)把每個分支的每一方當種物品,求解上述的揹包問題
這題不難,但卻用到了二部圖、求連通分支以及經典揹包問題變種等知識和技巧,而且還不是直接就可以看出應該如此求解,還得先進行一步轉換(即把朋友網路轉成 「敵人」 網路),確實是好題。當然,動態規劃部分不一定得套用揹包問題,例如,可以考慮狀態 f(i, d) ,前 i 個分支中,是否存在一種分組方式,使得兩隊人數之差為 d(可正可負)。於是,問題的解為使得 f(k, d)=true 的絕對值最小的那乙個d。這個思路也很直觀。不過,個人喜歡把未知問題轉換成已知問題來求解的思路。
USACO Hamming Codes 解題報告
資料小,暴力搜尋可以搞定。但是推薦使用dfs,每個節點 數 有取與不取兩個分支。注意 0是必須出現的。證明如下 最終得到的結果序列中,0是必須出現的,證明如下 如果存在另乙個滿足要求的結果序列s 其最小值為a1 n 0,那麼序列s s n 是滿足條件的最小解,且首元素為0 id xpli1 prog...
USACO Closed Fences 解題報告
幾何題看著就很有畏懼感。這裡用的是最 的演算法,時間複雜度應該在n 2。還沒看別人的解題報告,不過我猜nlogn的解法是有的。比如判斷乙個fence是不是valid的時候,這裡將所有的線段兩兩比較,看是否相交。但是有個叫line sweep的演算法,可以在nlogn的時間複雜度內完成。既然accep...
Wiggle Subsequence解題報告
這道題和最長子序列,divisible subset題目類似,都可以用o n2 的時間複雜度完成。可以想象,對於第i個數,dp i dp j 1,當且僅當dp j 1 dp i 而且nums j 和nums i 的差值和j所處位置的差值符號相反。所以,如下 class solution if dp ...