Guarding the Chessboard

Given an n ∗ 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, m (1 < n, m < 10) the size of
the chessboard. Next n lines each contain m 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.
Sample Input
8 8
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
8 8
X.......
.X......
..X.....
...X....
....X...
.....X..
......X.
.......X
0
Sample Output
Case 1: 5
Case 2: 1

 

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 int n,m,maxd,cas=0,vis[10][30];
 8 char s[15][15];
 9 
10 bool dfs(int cur,int r)
11 {
12     if(cur==maxd)
13     {
14         for(int i=1;i<=n;i++)
15         {
16             for(int j=1;j<=m;j++)
17                 if(s[i][j]=='X'&&!vis[0][i]&&!vis[1][j]&&!vis[2][i+j]&&!vis[3][i-j+11])///判断这个点是否被占领
18                     return false;
19         }
20         return true;
21     }
22 
23     for(int i=r;i<=n;i++)
24     {
25         for(int j=1;j<=m;j++)
26         {
27             if(!vis[0][i]||!vis[1][j]||!vis[2][i+j]||!vis[3][i-j+11])///行列副正
28             {
29                 int v1=vis[0][i],v2=vis[1][j],v3=vis[2][i+j],v4=vis[3][i-j+11];
30                 vis[0][i]=vis[1][j]=vis[2][i+j]=vis[3][i-j+11]=1;///修改全局变量
31                 if(dfs(cur+1,i+1))
32                     return true;
33                 vis[0][i]=v1;///改回来
34                 vis[1][j]=v2;
35                 vis[2][i+j]=v3;
36                 vis[3][i-j+11]=v4;
37             }
38         }
39     }
40     return false;
41 }
42 
43 int main()
44 {
45     while(~scanf("%d",&n)&&n)
46     {
47         scanf("%d",&m);
48         for(int i=1;i<=n;i++)
49             scanf("%s",s[i]+1);
50 
51         for(maxd=1;maxd<5;maxd++)///最大5个皇后
52         {
53             memset(vis,0,sizeof(vis));
54             if(dfs(0,0))
55                 break;
56         }
57         printf("Case %d: %d\n",++cas,maxd);
58     }
59     return 0;
60 }


附,八皇后问题的关键代码,便于比较

memset(vis,0,sizeof(vis));

void search_(int cur)
{
    if(cur==n)///递归边界
        tot++;
    else
    {
        for(int i=0;i<n;i++)
        {
            if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n])///列,副对角线,主对角线
            {
                C[cur]=i;///可以打印输出其位置
                vis[0][i]=vis[1][cur+i]==vis[2][cur-i+n]=1;///修改全局变量,以便递归
                search_(cur+1);
                vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;///切记,要变回来,下方的并没有基于上面的递归
            }
        }
    }
}

 

posted @ 2015-11-11 21:34  万俟天亮  阅读(263)  评论(0编辑  收藏  举报