UVa 11214 - Guarding the Chessboard

来源:互联网 发布:矩阵分子能量 编辑:程序博客网 时间:2024/05/07 12:28

題目:在一個nxm的棋盤上放上最少的皇后,使得給定的目標點(X)全部被占或者被攻擊。

分析:圖論,搜索。利用回溯法求解,需要加入一些剪枝提高效率。

            剪枝1:用當前找到的全局最小值剪枝,如果當前使用皇后數量不小於之前的最小值則拋棄;

            剪枝2:提前一步判斷,如果當前使用皇后數量+1不小於之前的最小值,且還存在X則拋棄;

            剪枝3:每次判斷當前皇后是否能夠消除X,如果不能則無須保留現場和回溯;

說明:跑了5s多╮(╯▽╰)╭。

#include <stdio.h>#include <stdlib.h>char maps[9][10];int  max = 0;void dfs(int n, int m, int d, int v){if (max <= v) {return;}int count = 0;for (int i = 0; i < n; ++ i) {for (int j = 0; j < m; ++ j) {count += (maps[i][j] == 'X');}}if (count == 0) {max = v;return;}else { // 剪枝可以,大幅度提高效率 if (max == v+1) {return;}}if (d >= n) {return;}char save[9][9], attack = -1;  for (int k = 0; k < m; ++ k) { // 在行內搜索if (attack) { // 上次沒有有效的 queue,不用再存儲for (int i = 0; i < n; ++ i) {for (int j = 0; j < m; ++ j) {save[i][j] = maps[i][j];}}}attack = 0; // 統計被攻擊到的目標,并刪除目標 for (int i = 0; i < n; ++ i) {for (int j = 0; j < m; ++ j) {if (i == d || j == k || i-d == j-k || i-d == k-j) {if (maps[i][j] == 'X') {maps[i][j] = '.';attack ++;}}}}if (attack) { // 存在有效目標則繼續搜索,并回溯 dfs(n, m, d, v+1);for (int i = 0; i < n; ++ i) { for (int j = 0; j < m; ++ j) {maps[i][j] = save[i][j];}}}}dfs(n, m, d+1, v); // 搜索下一行 }int main(){int n, m, cases = 1;while (~scanf("%d",&n) && n) {scanf("%d",&m);for (int i = 0; i < n; ++ i) {scanf("%s",maps[i]);}max = (n<m?n:m);dfs(n, m, 0, 0);printf("Case %d: %d\n", cases ++, max);}return 0;}
測試數據:

8 8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8 8X........X........X........X........X........X........X........X9 2XXXXXXXXXXXXXXXXXX2 2XXXX5 3XXXXXXXXXXXX...9 9.X...............X..............................X................X...........X...9 9XXXXXXXXXXXXXXXXXXXXXX.XXXXXXX.X.XXXXX.X.X.XXXXX.X.XXXXXXX.XXXXXXXXXXXXXXXXXXXXXX9 9XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2 2....7 7X......XX.....X.X..X.X......X..X...X......XXXXXXX0


0 0
原创粉丝点击