社区讨论
不输出求救,玄关
P1896[SCOI2005] 互不侵犯参与者 2已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @mdvolr4s
- 此快照首次捕获于
- 2025/08/03 20:52 7 个月前
- 此快照最后确认于
- 2025/11/04 03:15 4 个月前
CPP
#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;
}
回复
共 3 条回复,欢迎继续交流。
正在加载回复...