Description
Given an n∗mn∗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,mn,m (1<n,m<101<n,m<10) the size of the chessboard. Next nn lines each contain mm 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.
Samples
Input
8 8
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
8 8
X.......
.X......
..X.....
...X....
....X...
.....X..
......X.
.......X
0
Output
Case 1: 5
Case 2: 1
题目大意:
输入一个n∗mn∗m棋盘(n,m<10)(n,m<10),某些格子有标记。用最少的皇后守卫(即占据或者攻击)所有带标记的格子。
思路:
国际象棋中皇后的走法是横、竖、斜线都能走,所以直接DFS搜索即可。分别用x,y,y-x,x+y来标记行,列,主对角线和副对角线。
#include<bits/stdc++.h>
using namespace std;
int n,m,kase;
int g[10][10],vis[4][30];
int check() {
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if(g[i][j]&&!(vis[0][i]||vis[1][j]||vis[2][i+j]||vis[3][i-j+n]))
return 0;
return 1;
}
int iddfs(int st,int now,int maxd) {
if(now==maxd)
return check();
for(int i=st; i<n; i++)
for(int j=0; j<m; j++) {
if(vis[0][i]&&vis[1][j]&&vis[2][i+j]&&vis[3][i-j+n])
continue;
int tmp[4]= {0};
tmp[0]=vis[0][i],tmp[1]=vis[1][j],tmp[2]=vis[2][i+j],tmp[3]=vis[3][i-j+n];
vis[0][i]=vis[1][j]=vis[2][i+j]=vis[3][i-j+n]=1;
if(iddfs(i,now+1,maxd)) {
vis[0][i]=tmp[0],vis[1][j]=tmp[1],vis[2][i+j]=tmp[2],vis[3][i-j+n]=tmp[3];
return 1;
}
vis[0][i]=tmp[0],vis[1][j]=tmp[1],vis[2][i+j]=tmp[2],vis[3][i-j+n]=tmp[3];
}
return 0;
}
int main() {
cin>>n;
while(n) {
cin>>m;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++) {
char x;
cin>>x;
g[i][j]=x=='X'?true:false;
}
int maxd=0;
while(!iddfs(0,0,maxd))
maxd++;
printf("Case %d: %d\n",++kase,maxd);
cin>>n;
}
return 0;
}