专题一搜索 G - Guarding the Chessboard
- 题目
Given an n ∗ m chessboard with some marked squares, your task isto place as few queens as possible to guard (attack or occupy) allmarked squares. Below is a solution to an 8 ∗ 8 board with everysquare marked. Note that queens can be placed on non-markedsquares.
Input
The input consists of at most 15 test cases. Each case begins witha line containing two integers n, m (1 < n, m < 10) the size ofthe chessboard. Next n lines each contain m characters, ‘X’ denotesmarked square, ‘.’ denotes unmarked squares. The last case isfollowed by a single zero, which should not be processed.
Output
For each test case, print the case number and the minimal number of queens needed.
Sample Input
8 8
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
8 8
X.......
.X......
..X.....
...X....
....X...
.....X..
......X.
.......X
0
Sample Output
Case 1: 5
Case 2: 1 - 思路
八皇后问题的改编,不过看到有点低的通过数我意识到这玩意可能没那么简单
最后用了个东西叫迭代加深搜索
简单点说:八皇后问题一般都是dfs(算是dfs样板题),而为了在有限时间以内得到最优结果,每次深搜的时候限制搜索深度,依次尝试只放一个皇后两个皇后n个皇后可不可行,可行时停止加深输出结果。此外运行一次可以知道10*10放满的情况下最多5个皇后就能保卫棋盘,所以搜完4个皇后还没得到结果的话,答案肯定是5个皇后。 - 代码
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; int n,m; int vis[4][25]; int dep;//当前深度 char map[15][15]; bool dfs(int num,int r)//个数,行数 { if(num>dep) { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) if(map[i][j]=='X'&&!vis[0][i]&&!vis[1][j]&&!vis[2][i+j]&&!vis[3][i-j+m]) return 0; } return 1; } for(int i=r;i<=n;i++)//不一定每行都能放,比八皇后多一个循环 { for(int j=1;j<=m;j++) { if(!vis[0][i]||!vis[1][j]||!vis[2][i+j]||!vis[3][i-j+m]) { int v1=vis[0][i],v2=vis[1][j],v3=vis[2][i+j],v4=vis[3][i-j+m]; vis[0][i]=1, vis[1][j]=1, vis[2][i+j]=1, vis[3][i-j+m]=1; if(dfs(num+1,i+1)) return 1; vis[0][i]=v1,vis[1][j]=v2,vis[2][i+j]=v3,vis[3][i-j+m]=v4; } } } return 0; } int main() { int q=1; while(scanf("%d",&n)!=EOF&&n!=0) { scanf("%d",&m); getchar(); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%1c",&map[i][j]); } getchar(); } for(dep=1;dep<5;dep++)//10*10放满只需要5个皇后,搜完4个还没结果直接出答案 { memset(vis,0,sizeof(vis)); if(dfs(1,1)) break; } printf("Case %d: %d\n",q++,dep); } return 0; }