UVA - 11195 Another n-Queen Problem 位运算符+dfs

题目大意:给出一个n*n的一个棋盘,要求在这个棋盘上放置n个皇后。这个棋盘上的‘*’表示此处不能放置皇后,但不会影响皇后的攻击。问这样的棋盘,放置n个皇后有多少种放法

解题思路:因为n最多为15,所以可以用一个数表示每一行的状态。设置一个数组statu,记录刚开始每行能放置的状态,刚开始时能放置的位为0,不能放置的位为1。接下来一行一行枚举,回溯。dfs函数有四个参数,row,col,left,right

row:第几行

col:第row行的状态,1表示不能放,0表示可以放

left和right分别表示左斜线和右斜线的状态,还是0表可放,1表不可放

接下来将这个状态用“|”运算符结合起来,就可以得到该行的限制了,接着对这个限制进行取反运算"~",将0和1的状态表示替换一下,1表可放,0表不能放。

接着枚举可以放置的点,也就是找寻这个状态量中为1的点,从右往左找,这里有一个技巧,用这个状态量&(这个状态量-1再取反后的状态)&msk就可以得到最右边的1了。这里的msk主要是为了消除那些多余出来的列

#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 20
char str[maxn];
int statu[maxn], n, msk;
int dfs(int row, int col, int left, int right) {
	if(row == n)
		return 1;
	int ans = 0;
	int cur = ~(statu[row] | col | left | right);
	int last = cur&(-cur)&msk;
	while(last) {
		ans += dfs(row+1, col | last, (left | last) << 1, (right | last) >> 1);
		cur ^= last;
		last = cur&(-cur)&msk; 
	}
	return ans;
}

int main() {
	int mark = 1;
	while(scanf("%d", &n) == 1 && n) {
		msk = (1 << n) - 1;
		for(int i = 0; i < n; i++) {
			scanf("%s", str);
			statu[i] = 0;
			for(int j = 0; j < n; j++)
				if(str[j] == '*')
					statu[i] |= (1 << j);
		}
		printf("Case %d: %d\n",mark++, dfs(0,0,0,0));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值