博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
状压DP【p1896】[SCOI2005]互不侵犯
阅读量:4317 次
发布时间:2019-06-06

本文共 1412 字,大约阅读时间需要 4 分钟。

Description

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

Input

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

Output

所得的方案数

很明显\(N \leq 9\)状压DP啊 qwq.

这里有限制,我们只能放\(K\)个国王,并且如果一个格子有国王,其周围八个格子都不能放.

设状态\(f[i][j][k]\)代表前\(i\)行中第\(i\)行为\(j\)状态下共放了\(k\)个国王的方案数.

状态转移的话,我们当前行显然已经放了国王.

因此,转移可以很容易想到.

\[ f[i][j][l+calc(j)]+=f[i-1][k][l] \]
其中\(l\)为枚举的上一行所放的国王的个数,\(k\)为枚举的上一行的状态,\(calc(j)\)为计算\(j\)状态下有多少个国王被放置.

判断合法与否的话,只需要判断一下当前\(j\)状态与\(k\)状态\(&\)起来是否为零。

如何判断状态合法

判断是否\(j\)状态的某一位置右上方有无国王.

\[ (j>>1)&k==0 \]
同理左上方
\[ (j<<1)&k==0 \]
正上方
\[ j&k==0 \]
这几个方向是相对而言的.且我们从第\(1\)行到第\(n\)行放置的话,每次判断是否合法达到了判断6个方向的效果.

判断左右两侧当然是最简单的了

\[ j&(j>>1)==0\ \ && \ \ j&(j<<1)==0 \]

代码

#include
#define int long long#define R registerusing namespace std;int n,m,f[10][2048][108];int lim,ans;inline bool ok(int i){ return ((i&(i<<1))==0 and (i&(i>>1))==0);}//相邻方向. inline int calc(int x){ int res=0; for(R int i=0;(1<
<=x;i++) res+=(bool)(x&(1<
>1)&k)==0) { R int now=calc(j); for(R int l=0;l<=m;l++) f[i][j][l+now]+=f[i-1][k][l]; } } } } for(R int i=0;i<=lim;i++) ans+=f[n][i][m]; printf("%lld\n",ans);}

可以滚动数组滚掉第\(1\)维,切在枚举\(l\)的时候,第三维可能会超内存,因此要开大一点.当然也可以判断一下\(l+now \leq m\)

转载于:https://www.cnblogs.com/-guz/p/9794102.html

你可能感兴趣的文章
No qualifying bean of type available问题修复
查看>>
第四周助教心得体会
查看>>
spfile
查看>>
Team Foundation Service更新:改善了导航和项目状态速查功能
查看>>
WordPress资源站点推荐
查看>>
Python性能鸡汤
查看>>
android Manifest.xml选项
查看>>
Cookie/Session机制具体解释
查看>>
ATMEGA16 IOport相关汇总
查看>>
有意思的cmd命令
查看>>
js正則表達式语法
查看>>
Git学习系列-Git基本概念
查看>>
c#多个程序集使用app.config 的解决办法
查看>>
Linux+Apache+PHP+MySQL服务器环境配置(CentOS篇)
查看>>
Linux下获取本机IP地址的代码
查看>>
(C#)调用Webservice,提示远程服务器返回错误(500)内部服务器错误
查看>>
flex布局
查看>>
python-----python的文件操作
查看>>
java Graphics2d消除锯齿,使字体平滑显示
查看>>
控件中添加的成员变量value和control的区别
查看>>