标签:
Given an n ∗ m chessboard with some marked squares, your task is
to place as few queens as possible to guard (attack or occupy) all
marked squares. Below is a solution to an 8 ∗ 8 board with every
square marked. Note that queens can be placed on non-marked
squares.
Input
The input consists of at most 15 test cases. Each case begins with
a line containing two integers n, m (1 < n, m < 10) the size of
the chessboard. Next n lines each contain m characters, ‘X’ denotes
marked square, ‘.’ denotes unmarked squares. The last case is
followed 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
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 5 using namespace std; 6 7 int n,m,maxd,cas=0,vis[10][30]; 8 char s[15][15]; 9 10 bool dfs(int cur,int r) 11 { 12 if(cur==maxd) 13 { 14 for(int i=1;i<=n;i++) 15 { 16 for(int j=1;j<=m;j++) 17 if(s[i][j]==‘X‘&&!vis[0][i]&&!vis[1][j]&&!vis[2][i+j]&&!vis[3][i-j+11])///判断这个点是否被占领 18 return false; 19 } 20 return true; 21 } 22 23 for(int i=r;i<=n;i++) 24 { 25 for(int j=1;j<=m;j++) 26 { 27 if(!vis[0][i]||!vis[1][j]||!vis[2][i+j]||!vis[3][i-j+11])///行列副正 28 { 29 int v1=vis[0][i],v2=vis[1][j],v3=vis[2][i+j],v4=vis[3][i-j+11]; 30 vis[0][i]=vis[1][j]=vis[2][i+j]=vis[3][i-j+11]=1;///修改全局变量 31 if(dfs(cur+1,i+1)) 32 return true; 33 vis[0][i]=v1;///改回来 34 vis[1][j]=v2; 35 vis[2][i+j]=v3; 36 vis[3][i-j+11]=v4; 37 } 38 } 39 } 40 return false; 41 } 42 43 int main() 44 { 45 while(~scanf("%d",&n)&&n) 46 { 47 scanf("%d",&m); 48 for(int i=1;i<=n;i++) 49 scanf("%s",s[i]+1); 50 51 for(maxd=1;maxd<5;maxd++)///最大5个皇后 52 { 53 memset(vis,0,sizeof(vis)); 54 if(dfs(0,0)) 55 break; 56 } 57 printf("Case %d: %d\n",++cas,maxd); 58 } 59 return 0; 60 }
附,八皇后问题的关键代码,便于比较
memset(vis,0,sizeof(vis)); void search_(int cur) { if(cur==n)///递归边界 tot++; else { for(int i=0;i<n;i++) { if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n])///列,副对角线,主对角线 { C[cur]=i;///可以打印输出其位置 vis[0][i]=vis[1][cur+i]==vis[2][cur-i+n]=1;///修改全局变量,以便递归 search_(cur+1); vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;///切记,要变回来,下方的并没有基于上面的递归 } } } }
标签:
原文地址:http://www.cnblogs.com/moqitianliang/p/4957409.html