学校测试-2015-03-01
記得以前做N皇后問題見到過二進制+位運算優化的方法, 今天的搜索題第三題和第四題都可以用到二進制和位運算. 就只做了這兩個題目.
題目三
描述
傳遞游戲(pass)
Description
n個人在做傳遞物品的游戲,編號為1-n。
游戲規則是這樣的:開始時物品可以在任意一人手上,他可把物品傳遞給其他人中的任意一位;下一個人可以傳遞給未接過物品的任意一人。
即物品只能經過同一個人一次,而且每次傳遞過程都有一個代價;不同的人傳給不同的人的代價值之間沒有聯系;
求當物品經過所有n個人后,整個過程的最小總代價是多少。
Input Format
第一行為n,表示共有n個人(16>=n>=2);
以下為n*n的矩陣,第i+1行、第j列表示物品從編號為i的人傳遞到編號為j的人所花費的代價,特別的有第i+1行、第i列為-1(因為物品不能自己傳給自己),其他數據均為正整數(<=10000)。
Output Format
一個數,為最小的代價總和。
分析
- 狀壓DP, 二進制表示狀態(點到過或沒到過), 位運算實現查找和更新等操作
- f[i][k]表示狀態為 k 并且最后停留在 i 點時的最小代價
- => min{f[i][(1<<n)+1], (0<=i<n)}
- 轉移 :
枚舉狀態 k : 0 -> (1 << n) - 1
枚舉要更新的結點 i : 0 -> n-1
枚舉中間結點 j : 0 -> n-1, (i != j)
如果滿足 在狀態 k 中第 i 的位置為 0, 而第 j 的位置為 1, 那么就可以用 j 去更新 i. 核心 :
if(i != j && (k&(1 << j)) && !(k&(1 << i))) f[i][k^(1 << i)] = min(f[i][k^(1 << i)], f[j][k] + d[j][i]);初始化
f[i][1 << i] = 0, (0<=i<n)
表示從任意點出發
代碼
https://code.csdn.net/snippets/609746
題目四
描述
皇后守衛(queen)
Description
給一個N * M的棋盤,棋盤上的有些格子被打上了標記。現在需要在其中放置盡量少的皇后,使得所有被打上標記的格子至少被某一個皇后攻擊或占據到。皇后之間可以互相攻擊。
Input Format
輸入最多15組數據。
每組數據第一行包含兩個整數N和M(1 < N, M < 10),以下為一個N行M列的棋盤,其中打上標記的格子用‘X’表示,其它格子用‘.’表示。
輸入以一個0結尾。
Output Format
對于每組數據,輸出一個數表示最少需要使用的皇后數目。
分析
- 二進制+位運算優化+普通最優化剪枝的 dfs
- void dfs(int x, int row, int ld, int rd, int* k, int c)
x => 當前行
k => 數組, 表示當前所有被覆蓋的位置, 每一行都是用二進制表示的, 所以數組只需開一維
c => 計數變量, 已經放的皇后數
主函數調用dfs(0, 0, 0, 0, k, 0) // k 初始化全為 0 - 函數執行過程
如果該狀態下滿足了需要, 直接更新答案后返回
如果所以行已經考慮完了(x >= n), 直接返回
最優化剪枝 : 如果當前 c 不比已經記錄的 ans 更優, 直接返回
從當前行中選可以放置皇后的地方開始放皇后, 繼續dfs到下一層
該行不放皇后, dfs到下一層 許多精巧的位運算 :
- 判斷是否滿足條件, 標記的地方都被覆蓋到
枚舉 x, 如果所有 (k[x]&tar[x]) == tar[x] 說明滿足
解釋 : tar[x]表示第 x 行需要被覆蓋的二進制狀態. 只有當 tar[x] 為 1 的地方 k[x] 也為 1 才滿足 - 更新狀態, 在第 x 行二進制下 p 位置放置皇后對原可覆蓋狀態 k 的影響
解釋 : upperlim = (1 << n) - 1
首先 x 行應該全變為 1, 也就是 k[x] 狀態為 upperlim
再考慮對角線和列
對p的解釋 : p 的二進制中只有一位為 1, 也就是皇后所在列的那一位- 判斷是否滿足條件, 標記的地方都被覆蓋到
- 其他
- ans 可以初始化為 5
在 9*9 全 ‘X’ 的棋盤上 - 皇后可以互相攻擊, 也就是同一行上可以有多個皇后
- ans 可以初始化為 5
代碼
https://code.csdn.net/snippets/609744
總結
以上是生活随笔為你收集整理的学校测试-2015-03-01的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [总结] 平衡树总结
- 下一篇: BZOJ-3173-最长上升子序列