传送门UVa 639 & HOJ 1086 & POJ 1315 - Don't Get Rooked
刚开始想用超级暴力法做,就是尝试在每一格先放上一个棋子,然后从头开始暴力。但是WA了几次,发现这个算法有缺陷。早上晨跑的时候忽然想到前不久看到一个很神奇的随机算法,或许可以试一下。。有空再来。
后来采用的是回溯,不过感觉还是挺暴力的,每次放棋子都要扫描上下左右,感觉应该有更好的解决办法。但是以我目前的水平想不到。。、
思路就是回溯+判断是否合理。和以前的题目差不多。
在写的时候遇到一个小问题,就是max变量,在STL中有专门用处,所以不能用这个变量名字,不知道大家是用什么名字的。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int vis[8][8];
char maze[8][8];
int cnt, mmax, n;
void DFS(int cnt);
int main()
{
//freopen("input.txt", "r", stdin);
int i, j;
while (scanf("%d%*c", &n) && n)
{
mmax = 0;
cnt = 0;
memset(maze, 0, sizeof(maze));
memset(vis, 0, sizeof(vis));
for (i = 0; i < n; i++)
gets(maze[i]);
DFS(0);
printf("%d\n", mmax);
}
return 0;
}
bool Judge(int a, int b)
{
//检查当前点的上下左右
for (int j = b + 1; j < n && maze[a][j] != 'X'; j++) //碰到X就不用再检查了,已经合理
if (vis[a][j])
return false;
for (int j = b - 1; j >= 0 && maze[a][j] != 'X'; j--)
if (vis[a][j])
return false;
for (int j = a + 1; j < n && maze[j][b] != 'X'; j++)
if (vis[j][b])
return false;
for (int j = a - 1; j >= 0 && maze[j][b] != 'X'; j--)
if (vis[j][b])
return false;
return true;
}
void DFS(int cnt)
{
mmax = max(cnt, mmax);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
if (!vis[i][j] && Judge(i, j) && maze[i][j] == '.')
{
vis[i][j] = 1;
DFS(cnt + 1);
vis[i][j] = 0;
}
}
}