题意:输入一个 n∗m 棋盘 (n,m<10) ,某些格子有标记。用最少的皇后守卫(即占据或者攻击)所有带标记的格子。(本段摘自《算法竞赛入门经典(第2版)》
分析:
直接DFS搜索即可。分别用x,y,y-x,x+y来标记行,列,主对角线和副对角线。
代码:
#include <iostream>
#include <algorithm>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <cctype>
#include <stack>
#include <set>
using namespace std;
const int maxn = 10 + 5, INF = 1e8;
struct Node
{
int x, y;
Node(int x, int y) : x(x), y(y) {}
};
int n, m, C;
int v[4][maxn << 1];
char a[maxn][maxn];
vector< Node > vec;
bool judge()
{
int l = vec.size();
for (int i = 0; i < l; ++i)
if (!v[0][vec[i].x] && !v[1][vec[i].y] && !v[2][vec[i].y - vec[i].x + n] && !v[3][vec[i].x + vec[i].y])
return false;
return true;
}
bool DFS(int cur, int deep, int maxd)
{
if (deep == maxd)
{
if (judge())
return true;
return false;
}
for (int pos = cur; pos < n * m; ++pos)
{
int x = pos / m, y = pos % m;
int tmp_a = v[0][x], tmp_b = v[1][y], tmp_c = v[2][y - x + n], tmp_d = v[3][x + y];
v[0][x] = 1;
v[1][y] = 1;
v[2][y - x + n] = 1;
v[3][x + y] = 1;
if (DFS(pos, deep + 1, maxd))
return true;
v[0][x] = tmp_a;
v[1][y] = tmp_b;
v[2][y - x + n] = tmp_c;
v[3][x + y] = tmp_d;
}
return false;
}
int main()
{
while (~scanf("%d", &n), n)
{
vec.clear();
scanf("%d", &m);
for (int i = 0; i < n; ++i)
scanf("%s", a[i]);
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
if (a[i][j] == 'X')
vec.push_back(Node(i, j));
for (int maxd = 0; ; ++maxd)
{
memset(v, 0, sizeof(v));
if (DFS(0, 0, maxd))
{
printf("Case %d: %d\n", ++C, maxd);
break;
}
}
}
return 0;
}