習題7-10:守衛棋盤
給出m*n棋盤上的目標點,求最少用幾個皇后可以守衛所有目標點。
類似八皇后做法,2維數組標記行、列、主對角線、副對角線。
有個加速的技巧,測試之後發現10*10的棋盤全部守衛至少需要5個,所以上限就是5,當maxd等於5時直接輸出,不進行搜索。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<map>
#include<stack>
#include<vector>
#include<list>
#include<deque>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const double eps = 1e-6;
const int INF = 1 << 30;
const int dir[4][2] = {1,0,0,1,0,-1,-1,0};
int n, m, maxd;
bool Map[12][12], vis[4][50];
bool input()
{
cin >> n;
if(!n)return false;
cin >> m;
char x;
memset(Map, 0, sizeof(Map));
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
cin >> x;
if(x == 'X')Map[i][j] = 1;
}
}
return true;
}
bool judge()
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(Map[i][j] && !vis[0][i] && !vis[1][j] && !vis[2][i + j] && !vis[3][i - j + 11])return false;
}
}
return true;
}
bool dfs(int d, int i, int j)
{
if(d == maxd)
{
if(judge())return true;
return false;
}
for(; i < n; i++)
{
for(; j < m; j++)
{
bool tmp1 = vis[0][i], tmp2 = vis[1][j], tmp3 = vis[2][i + j], tmp4 = vis[3][i - j + 11];
vis[0][i] = vis[1][j] = vis[2][i + j] = vis[3][i - j + 11] = 1;
if(dfs(d + 1, i, j + 1))return true;
vis[0][i] = tmp1;
vis[1][j] = tmp2;
vis[2][i + j] = tmp3;
vis[3][i - j + 11] = tmp4;
}
j = 0;
}
return false;
}
int main()
{
int cases = 0;
while(input())
{
for(maxd = 0; maxd < 5; maxd++)
{
memset(vis, 0, sizeof(vis));
if(dfs(0, 0, 0))break;
}
printf("Case %d: %d\n", ++cases, maxd);
}
return 0;
}