不输出求救,玄关
查看原帖
不输出求救,玄关
1200191
封禁用户楼主2025/8/3 20:51
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, k, dp[9][1<<9][90];
//N最大为9,所以i最大为9,所以st最大为111111111的十进制数即1<<9,K<=N*N,N最大为9,所以K最大为81,以防万一开大点

//n,k为题目所给的棋盘行列数及国王数,dp为状态压缩数组
//dp[i][st][j]中第一维为当前在第i行或者说已经经过了i行(包括当前行)
//第三维表示直到当前行已经放了j个国王
int ans;
inline int c(int st){//算st的二进制表示中有多少个"国王"(1)
	int cnt=0;
	while(st){
		if(st % 2)cnt++;
		st/=2;
	}
	return cnt;
}
bool check1(int st){//判断st是否合法,即不能存在连续的“国王”(1)(包括行间与列间)这里为列间
	for(int i = 1; i + 1 < n; i++){
		if(st & (1 << i) && (st & (1 << (i + 1)))){//判断st第i位是否为1,不返回0即st[i]为1,如果连续两位都是1,就说明不合法
		    return false;
		}
	}
	return true;
}
bool check2(int st, int st2){//这里为行间,st2为上一行的状态
	for(int i = 1; i < n; i++){
		if(st & (1 << i)){
			if(st2 & (1 << i)) return false;
			else if(i + 1 < n && st2 & (1 << (i+1))) return false;
			else if(i - 1 < n && (st2 & (1 << (i - 1)))) return false;
		}
	}
	return true;
}
signed main(){
	cin>>n>>k;
	for(int i = 1; i < n; i++){
		for(int st = 1; st < (1 << n); st++){
			if(!check1(st))continue;
			if(i == 0) dp[i][st][c(st)] = 1;
			else{
				for(int j = c(st); j <= k; j++){
					for(int st2 = 1; st < (1 << n); st2++){
						if(!check1(st2) || !check2(st, st2)){
							continue;
						}
						dp[i][st][j]=dp[i-1][st2][j-c(st)];
					}
				}
			}
		}
	}//当st不合法,dp为0
	for(int st = 0; st < (1 << n); st++){
		ans+=dp[n-1][st][k];
	}
	cout<<ans<<"\n";
	return 0;
}
2025/8/3 20:51
加载中...