小国王(状态压缩dp)

小国王

#include<bits/stdc++.h>
using namespace std;

int n,k;//棋盘行数 国王总数 
int cnt;//同一行的合法状态个数 
int s[1<<12];//同一行的合法状态集 
int num[1<<12];//每个合法状态包含的国王数 
long long f[12][144][1<<12];
 

//f[i,j,a]表示前i行放了j个国王  第i行第a个状态时的方案数 
int main(){
	cin>>n>>k;//输入行数  国王总数 
	
	for(int i=0;i<(1<<n);i++)//枚举一行的所有状态 
		if(!(i&i>>1)){//如果不存在相邻的1 
			s[cnt++] = i;//保存一行的合法状态 
			for(int j=0;j<n;j++)
				num[i]+=(i>>j&1);//统计每个合法状态包含的国王数 
		}
	
	f[0][0][0] = 1;//不放国王也是一种方案 
	for(int i=1;i<=n+1;i++)//枚举行 
		for(int j=0;j<=k;j++)//枚举国王数 
			for(int a=0;a<cnt;a++)//枚举第i行的合法状态 
				for(int b=0;b<cnt;b++){//枚举第i-1行的合法状态 
					int c = num[s[a]];//第i行第a个状态的国王数 
					
					//可以继续放国王 不存在同列的1        不存在斜对角的1 
					//c为每个状态需要的国王数 所以j>=c 
					// s[b]&s[a]判断是否在同一列上
					// (s[b] & (s[a]>>1))判断是否在左上角
					// (s[b] & (s[a]<<1))判断是否在右上角
					if((j>=c) && !(s[b]&s[a]) && !(s[b] & (s[a]<<1)) && !(s[b] & (s[a]>>1)))
					f[i][j][a] += f[i-1][j-c][b];
				} 
	
	
	
	cout<<f[n+1][k][0]<<endl;//第n+1行什么都不放 相当于只在1~n行放国王 
	
	return 0;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值