J . Guarding the Chessboard

Description

Given an n∗mn∗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 88 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,mn,m (1<n,m<101<n,m<10) the size of the chessboard. Next nn lines each contain mm 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.

Samples

Input 

8 8
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
8 8
X.......
.X......
..X.....
...X....
....X...
.....X..
......X.
.......X
0

Output

Case 1: 5
Case 2: 1

 题目大意:

输入一个n∗mn∗m棋盘(n,m<10)(n,m<10),某些格子有标记。用最少的皇后守卫(即占据或者攻击)所有带标记的格子。

思路:

国际象棋中皇后的走法是横、竖、斜线都能走,所以直接DFS搜索即可。分别用x,y,y-x,x+y来标记行,列,主对角线和副对角线。

#include<bits/stdc++.h>
using namespace std;
int n,m,kase;
int g[10][10],vis[4][30];
int check() {
	for(int i=0; i<n; i++)
		for(int j=0; j<m; j++)
			if(g[i][j]&&!(vis[0][i]||vis[1][j]||vis[2][i+j]||vis[3][i-j+n]))
				return 0;
	return 1;
}
int iddfs(int st,int now,int maxd) {
	if(now==maxd)
		return check();
	for(int i=st; i<n; i++)
		for(int j=0; j<m; j++) {
			if(vis[0][i]&&vis[1][j]&&vis[2][i+j]&&vis[3][i-j+n])
				continue;
			int tmp[4]= {0};
			tmp[0]=vis[0][i],tmp[1]=vis[1][j],tmp[2]=vis[2][i+j],tmp[3]=vis[3][i-j+n];
			vis[0][i]=vis[1][j]=vis[2][i+j]=vis[3][i-j+n]=1;
			if(iddfs(i,now+1,maxd)) {
				vis[0][i]=tmp[0],vis[1][j]=tmp[1],vis[2][i+j]=tmp[2],vis[3][i-j+n]=tmp[3];
				return 1;
			}
			vis[0][i]=tmp[0],vis[1][j]=tmp[1],vis[2][i+j]=tmp[2],vis[3][i-j+n]=tmp[3];
		}
	return 0;
}
int main() {
	cin>>n;
	while(n) {
		cin>>m;
		for(int i=0; i<n; i++)
			for(int j=0; j<m; j++) {
				char x;
				cin>>x;
				g[i][j]=x=='X'?true:false;
			}
		int maxd=0;
		while(!iddfs(0,0,maxd))
			maxd++;
		printf("Case %d: %d\n",++kase,maxd);
		cin>>n;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值