P1896

[SCOI2005] 互不侵犯

题目描述

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

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

输入格式

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

输出格式

所得的方案数

样例 #1

样例输入 #1

3 2

样例输出 #1

16
woc
我第一次纯自己写状压一遍写对!
状压注意细节!!!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int k,n;
int f[10][85][(1<<10)];
signed main()
{
	ios::sync_with_stdio(false);
	cin>>n>>k;
	for(int t=0;t<(1<<n);t++)
	{
		int flag=1;
		for(int l=0;l<n;l++)
			if((t&(1<<l))&&(t&(1<<(l+1))))
			{
				flag=0;
				break;
			}			
		if(!flag)continue;
		int cnt=0;
		for(int l=0;l<n;l++)
			if(t&(1<<l))
				cnt++;
		f[1][cnt][t]=1;
	}
	int cnt1,cnt2;
	for(int i=2;i<=n;i++)
	{
		for(int j=0;j<=k;j++)
		{
			for(int t=0;t<(1<<n);t++)
			{
				cnt1=0;cnt2=0;
				for(int p=0;p<n;p++)
					if(t&(1<<p))cnt1++;
				int flag=1;
				for(int p=0;p<n;p++)
					if((t&(1<<p))&&(t&(1<<(p+1))))
					{
						flag=0;
						break;
					}
				if(!flag)continue;
				for(int l=0;l<(1<<n);l++)
				{
					int pd=1;
					for(int p=0;p<n;p++)
					{
						if((l&(1<<p))&&(t&(1<<p))){pd=0;break;}
						if((l&(1<<p))&&(t&(1<<(p+1)))){pd=0;break;}
						if((l&(1<<p))&&(t&(1<<(p-1)))){pd=0;break;}
					}
					if(!pd)continue;
					for(int p=0;p<n;p++)
						if(l&(1<<p))cnt2++;
					if(j-cnt1>=0)
					f[i][j][t]+=f[i-1][j-cnt1][l];
				}
			}
		}
	}
	int tot=0;
	for(int t=0;t<(1<<n);t++)
	{
		int cnt=0;
		for(int p=0;p<n;p++)
			if(t&(1<<p))cnt++;
		if(k>=cnt)
			tot+=f[n][k][t];
	}
	cout<<tot<<"\n";
	return 0;
}
posted @ 2023-01-19 21:23  PKU_IMCOMING  阅读(3)  评论(0)    收藏  举报