题意:输入一个n*m棋盘(0<n,m<10),某些格子有标记。用最少的皇后守卫所有带标记的格子。皇后规则是所在坐标的直线和斜线都可以被守卫,长度不限。
分析:因为不知道深度,所以用迭代加深搜索,判断条件可以参照之前写的八皇后问题。
具体就是回溯二分。
# include<iostream>
# include<cstdio>
# include<cmath>
# include<map>
# include<queue>
# include<string>
# include<string.h>
#include<set>
#include<list>
# include<algorithm>
using namespace std;
int row, col;
int maxd;
char mp[10][10];
int vis[4][30];
bool judge() {
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
if (mp[i][j]=='X' && !vis[0][j] && !vis[1][i] && !vis[2][i + j] && !vis[3][j - i + 10])return false;
return true;
}
bool dfs(int cur,int count0) {
if (count0 == maxd) {
if (judge()) {
return true;
}
else return false;
}
else {
for (int k = cur; k < row*col; k++) {
int i = k / col;
int j = k % col;
int n1 = vis[0][j]; int n2 = vis[1][i]; int n3 = vis[2][i + j]; int n4 = vis[3][j - i + 10];
vis[0][j] = vis[1][i] = vis[2][i + j] = vis[3][j - i + 10] = 1;
if (dfs(k, count0 + 1))return true;
vis[0][j] = n1; vis[1][i] = n2; vis[2][i + j] = n3; vis[3][j - i + 10] = n4;
}
}
return false;
}
int main() {
string x; int kase = 0;
while (scanf("%d", &row)&&row) {
scanf("%d", &col);
memset(mp, 0, sizeof(mp));
memset(vis, 0, sizeof(vis));
for (int i = 0; i < row; i++) {
cin >> mp[i];
}
for (maxd = 0;; maxd++) {
memset(vis, 0, sizeof(vis));
if(dfs(0,0))break;
}
printf("Case %d: %d\n", ++kase, maxd);
}
return 0;
}