码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1087 SCOI 2005 互不侵犯King 状压DP

时间:2014-11-21 18:53:36      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:bzoj   scoi2005   状压dp   递推   

题目大意:一个国王可以攻击到旁边8个位置的格子,现在给出一个N*N的方格,向其中放k个国王,问有多少中摆放方法。


思路:状压DP,f[i][j][k],其中i是行数,j是状态,k是已经取了多少国王。然后暴力枚举状态,看相邻两行之间有没有冲突,若没有冲突,那么就转移。

注意要开long long 


CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

int cnt,k;
long long f[15][1000][100];

inline int Set(int status)
{
	int re = 0;
	while(status)
		re += status&1,status >>= 1;
	return re;
}

inline bool Judge(int x,int y)
{
	static bool v[11];
	memset(v,false,sizeof(v));
	int p = 1;
	while(x) {
		if(x&1) {
			if(v[p - 1]|v[p]|v[p + 1])	return false;
			 v[p] = true;
		}
		x >>= 1;
		++p;
	}
	p = 1;
	while(y) {
		if(y&1) {	
			if(v[p - 1]|v[p]|v[p + 1])	return false;
			v[p] = true;
		}
		y >>= 1;
		++p;
	}
	return true;
}

int main()
{ 
	cin >> cnt >> k;
	for(int status = 0; status < (1 << cnt); ++status)
		if(Judge(status,0))
			f[1][status][Set(status)] = 1;
	for(int i = 2; i <= cnt; ++i)
		for(int s = 0; s < (1 << cnt); ++s)
			for(int _s = 0; _s < (1 << cnt); ++_s)
				if(Judge(s,_s)) {
					int temp = Set(_s);
					for(int z = 0; z <= k - temp; ++z)
						f[i][_s][z + temp] += f[i - 1][s][z];
				}
	long long ans = 0;
	for(int status = 0; status < (1 << cnt); ++status)
		ans += f[cnt][status][k];
	cout << ans << endl;
	return 0;
}


BZOJ 1087 SCOI 2005 互不侵犯King 状压DP

标签:bzoj   scoi2005   状压dp   递推   

原文地址:http://blog.csdn.net/jiangyuze831/article/details/41351477

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!