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;///切记,要变回来,下方的并没有基于上面的递归
            }
        }
    }
}
时间: 2024-07-30 13:47:37

Guarding the Chessboard的相关文章

Guarding the Chessboard(UVa 11214)

本题题意: 输入一个n*m的棋盘,某些格子有标记,用最少的皇后占据或者攻击所以带标记的格子.皇后的攻击范围为同行同列和同对角线. 可以使用IDA*算法,即从样例可以发现只需要最多5个棋子就可以对棋盘上所有地方进行攻击,因而使用IDA*进行对应的剪枝即可. #include<cstdio> #include<cstring> using namespace std; int n,m,kase=0,maxd; bool vis[4][30];///表示皇后已经攻击的范围,vis[0][

UVA-11214 Guarding the Chessboard (迭代加深搜索)

题目大意:在一个国际象棋盘上放置皇后,使得目标全部被占领,求最少的皇后个数. 题目分析:迭代加深搜索,否则超时. 小技巧:用vis[0][r].vis[1][c].vis[2][r+c].vis[c-r+N]分别标志(r,c)位置相对应的行.列.主.副对角线有没有被占领(详见<入门经典(第2版)>P193),其中N表示任意一个比行数和列数都大(大于等于)的数. 代码如下: # include<iostream> # include<cstdio> # include&l

UVa11214 Guarding the Chessboard (IDA*)

链接:http://vjudge.net/problem/23958 分析:控制最大递归深度为maxd,也就是枚举个数maxd个皇后守卫的时候,dfs以行枚举放皇后守卫的位置,确保放皇后守卫的位置的行,列,主和副对角线上没有其它守卫,否则就不是最优的了,每次递归从上次放的行的下一行开始放,放满maxd个后进行判断是否所有标记格子都被攻击到.是则直接返回true输出最少守卫,否则返回递归上一层继续枚举,vis要复位. 1 #include <cstdio> 2 #include <cstr

11214 - Guarding the Chessboard(暴力搜索)

IDA*算法, 从小到大枚举深度上限,不过该题是有深度上限的,题目中的第一个样例表明:最多需要5个皇后就可以覆盖整个棋盘 . 利用紫书上的技巧,我们可以快速的判断任意两个棋子是不是在同一行.同一列.同一对角线 (详情见紫书P193那两个图). 这样之后暴力搜索就可以了 . 每一层需要O(nm)的复杂度,但是实际上并不需要那么大的复杂度 .和八皇后问题类似 , 当前行之前的行已经放置了皇后,所以不必在管,每次从下一行开始放置就好 . 细节见代码: #include<bits/stdc++.h>

UVa11214 - Guarding the Chessboard

给出m*n棋盘上的目标点,求最少用几个皇后可以守卫所有目标点. 类似八皇后做法,2维数组标记行.列.主对角线.副对角线. 有个加速的技巧,测试之后发现10*10的棋盘全部守卫至少需要5个,所以上限就是5,当maxd等于5时直接输出,不进行搜索. #include<cstdio> #include<cstring> using namespace std; const int maxn=11; int n,m,t,maxd; bool g[maxn][maxn],vis[4][max

UVA 11214 Guarding the Chessboard 守卫棋盘(迭代加深+剪枝)

就是个暴力,和八皇后很像,但是还是要加一些的剪枝的. 1.最裸的暴搜 6.420s,差点超时 2.之前位置放过的就没必要在放了,每次从上一次放的位置开始放 0.400s #include<cstdio> #include<cstring> const int maxn = 11; char G[maxn][maxn]; int maxd; int n,m; bool visi[maxn],visj[maxn],vis1[maxn<<1],vis2[maxn<<

UVA - 11214 Guarding the Chessboard (可重复覆盖,DLX+IDA*)

题目链接 正解是IDA*+四个方向判重,但由于是个裸的可重复覆盖问题,可以用DLX水过~ 每个格子与放上皇后能干掉的标记连边,跑可重复覆盖DLX.注意要用IDA*来优化,否则会超时. 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=10+2; 5 int n,m,np,ka; 6 char s[N][N]; 7 struct P {int x,y;} p[N*N]; 8

POJ——T2446 Chessboard

http://poj.org/problem?id=2446 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18560   Accepted: 5857 Description Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of c

POJ 3344 &amp; HDU 2414 Chessboard Dance(模拟)

题目链接: PKU:http://poj.org/problem?id=3344 HDU:http://acm.hdu.edu.cn/showproblem.php?pid=2414 Description Another boring Friday afternoon, Betty the Beetle thinks how to amuse herself. She goes out of her hiding place to take a walk around the living r