互不侵犯KING
题意:一个 的棋盘,有 个国王,问有几种摆放的情况?
思路:爆搜直接寄,状压DP,将一行的状态表示为二进制状态比如101001,1表示这个位置放国王,然后转化成10进制数字,状压DP的套路就
是不断枚举每个状态的数字,判断这种状态符不符合。
状态设置:
我们设置
转移方程:
红色表示国王,蓝色是攻击范围,当我们第i-1行的第j列有国王时,第i行有什么影响呢?
- 第i行的第j列,第j+1,j-1列都不能放了。我们用
表示第i-1行的状态, 表示i行的状态,那么就是当(S2&S1==0)&&((S2<<1)&S1)==0&&((S2>>1)&S1==0 - 第
行来说,那么就需要满足((S2<<1)&S2==0)&&((S2>>1)&S2==0);
然后考虑第二维的国王数是怎么转移的,对第i-1行来说,第i行多放的国王数就是第i行上的1的个数,我们用__builtin_popcount这个函数快速找到,那么转移方程式即是:
初始化细节提示:
代码:
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k;
int f[10][100][1<<11];
int cnt[1<<11];
int st[1<<11];
//int king [1<<11],state[1<<11];
//int tot,ans;
//void init(){
// tot=(1<<n)-1;
// for (int i = 0; i <=tot ; ++i) {
// if(!((i<<1)&i)){
// state[++ans]=i;
// int t=i;
// while (t){
// king[ans]+=t%2,t>>=1;
// }
// }
// }
//}
int num;
void init(){
for (int s = 0; s <(1<<n) ; ++s) {
cnt[s]=__builtin_popcount(s);
if((((s<<1)|(s>>1))&s)==0) st[++num]=s;
}
}
void solve(){
cin>>n>>k;
init();
//当前的第i行,状态为S时,用了j个国王的方案数
f[0][0][0]=1;
for (int i = 1; i <=n ; ++i) {
for (int tem = 1; tem <=num ; ++tem) {
int s1=st[tem];
for (int last = 1; last <=num ; ++last) {
int s2=st[last];
if(((s2|(s2<<1)|(s2>>1))&s1)==0){
for (int j = 0; j <=k ; ++j) {
if(j-cnt[s1]>=0){
f[i][j][s1]+=f[i-1][j-cnt[s1]][s2];
}
}
}
}
}
}
// for(int i=1;i<=n;i++) //枚举我们已经放到了第几行
// {
// for(int l=1;l<=num;l++) //枚举第i行的状态,这里我们直接枚举所有满足条件2的状态,算是个优化吧
// {
// int s1=st[l];
// for(int r=1;r<=num;r++) //枚举上一行的状态
// {
// int s2=st[r];
// if(((s2|(s2<<1)|(s2>>1))&s1)==0) //如果上下,左下右上,左上右下方向都不相邻,合法
// {
// for(int j=0;j<=k;j++) //枚举国王个数
// if(j-cnt[s1]>=0)
// f[i][j][s1]+=f[i-1][j-cnt[s1]][s2]; //状态转移方程
// }
// }
// }
// }
int ans=0;
// cout<<num<<' ';
for (int i = 1; i <=num ; ++i) {
ans+=f[n][k][st[i]];
// cout<<f[n][k][st[i]]<<' ';
}
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t=1;
//cin>>t;
while (t--)solve();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】