1592:【例 1】国王(状态压缩

【题目描述】

原题来自:SGU 223

在 n×nn×n 的棋盘上放 kk 个国王,国王可攻击相邻的 88 个格子,求使它们无法互相攻击的方案总数。

【输入】

只有一行,包含两个整数 nn 和 kk。

【输出】

每组数据一行为方案总数,若不能够放置则输出 00。

【输入样例】

3 2

【输出样例】

16

【提示】

样例输入 2

4 4

样例输出 2

79

数据范围与提示:

对于全部数据,1≤n≤10,0≤k≤n21≤n≤10,0≤k≤n2 。

1592:【例 1】国王icon-default.png?t=N7T8https://ybt.ssoier.cn/problem_show.php?pid=1592

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N=15,M=1<<11,K=110;
int n,m;
long long f[N][K][M];//在第i行,已经摆放了j个国王,当前行状态为k的方案数
int cnt[M];
vector<int> state;//存放合法状态 
vector<int> h[M];//存放当前状态上一行的合法状态 

bool check(int u){
	for(int i=0;i<n;i++)
		if((u>>i)&1&&(u>>i+1)&1)return false;
	return true;
} 

int count(int u){
	int cnt=0;
	for(int i=0;i<n;i++)cnt+=(u>>i)&1;
	return cnt;
}

int main(){
	cin>>n>>m;
	
	for(int i=0;i<(1<<n);i++)
		if(check(i)){
		state.push_back(i);
		cnt[i]=count(i);
		}
	
	for(int i=0;i<state.size();i++)
		for(int j=0;j<state.size();j++){
			int a=state[i],b=state[j];
			if(check(a|b)&&(a&b)==0)
			h[i].push_back(j);
		}

	f[0][0][0]=1;
	
	for(int i=1;i<=n+1;i++){
		for(int j=0;j<=m;j++){
			for(int a=0;a<state.size();a++){
				for(int &b:h[a]){
					int c=cnt[state[a]];
					if(j>=c)
						f[i][j][a]+=f[i-1][j-c][b];
				}
			}
		}
	}
	long long res = 0;
	for(int a = 0; a < state.size(); a++){
    res += f[n][m][a];  // 累加符合条件的方案数
	}
		
	cout<<res;//或者cout<<f[n+1][m][0] 
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值