状压DP【洛谷P1896】 [SCOI2005]互不侵犯

P1896 [SCOI2005]互不侵犯

题目描述

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

注:数据有加强(2018/4/25)

输入输出格式

输入格式:

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

输出格式:

所得的方案数

\(continue\)\(break\)傻傻分不清,也是挺厉害了。。。

code:

#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
inline int read(){
	int sum=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
	return sum*f;
}

int n,m,ans;
int f[11][1<<10][101];
signed main(){
	n=read();m=read();
	int WX=(1<<n);
	f[0][0][0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<WX;j++)
		{
			int flag=0,tot=0;
			for(int tmp=1;tmp<=n;tmp++)
			{
				if(j&(1<<tmp-1))tot++;
				if(((j&(1<<tmp-1))&&((j&(1<<tmp)))))
				{
					flag=1;break;
				}
			}
			if(flag)continue;
			if(tot>m)continue;
			for(int k=0;k<WX;k++)
			{
				int flag=0;
				for(int tmp=1;tmp<=n;tmp++)
				{
					if(((k&(1<<tmp-1))&&((k&(1<<tmp)))))
					{
						flag=1;break;
					}
				}
				if(flag)continue;
				for(int tmp=1;tmp<=n;tmp++)
				{
					if(((k&(1<<tmp-1))&&(j&(1<<tmp)))||((k&(1<<tmp-1))&&(j&(1<<(tmp-1))))||((k&(1<<tmp-1))&&(j&(1<<(tmp-2)))))
					{
						flag=1;break;
					}
				}
				if(flag)continue;
				for(int l=tot;l<=m;l++)
				{
					f[i][j][l]+=f[i-1][k][l-tot];
				}
			}
		}
	}
	for(int i=0;i<WX;i++){
		ans+=f[n][i][m]; 
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2018-10-15 21:19  _王小呆  阅读(116)  评论(0编辑  收藏  举报