P1869 互不侵犯(简单的状压DP)
题意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到周围的八个格子。
题解:首先只考虑某一行合法的摆法,只需保证选的格子不相邻就行。
可以把一行里合法的状态用一串二进制数存起来,每个数第i位的1表示第i列放置国王
比如101001是合法的,101101是不合法的
预处理每一种合法状态中,选择的格子数为 sta(x)
设f(i,j,l)表示已经处理到第i行,本行状态为j,总共已经选了l个的方案总数
设上一行的状态为x,如果x和j不矛盾就可以得到状态转移方程
f(i,j,l)=Σf(i-1,x,l-sta(x))
那么答案就是Σf(n,i,k)

1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 long long sta[2005], sit[2005], f[15][2005][105]; 6 7 int n, k, cnt; 8 9 void dfs(int x,int num,int cur){ 10 11 if(cur>=n){ 12 13 sit[++cnt]=x; 14 15 sta[cnt]=num; 16 17 return; 18 19 } 20 21 dfs(x,num,cur+1); 22 23 dfs(x+(1<<cur),num+1,cur+2); 24 25 } 26 27 int main(){ 28 29 cin>>n>>k; 30 31 dfs(0,0,0); 32 33 for(int i=1;i<=cnt;++i)f[1][i][sta[i]]=1; 34 35 for(int i=1;i<=n;++i) 36 37 for(int j=1;j<=cnt;++j) 38 39 for(int l=1;l<=cnt;++l){ 40 41 if (sit[j] & sit[l]) continue; 42 43 if ((sit[j] << 1) & sit[l]) continue; 44 45 if (sit[j] & (sit[l] << 1)) continue; 46 47 for(int p=sta[j];p<=k;++p) 48 49 f[i][j][p]+=f[i-1][l][p-sta[j]]; 50 51 } 52 53 long long ans = 0; 54 55 for(int i=1;i<=cnt;++i) 56 57 ans+=f[n][i][k]; 58 59 cout<<ans<<endl; 60 61 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律