当前位置:网站首页>【[SCOI2005] 互不侵犯】【状压DP(含概念讲解)】
【[SCOI2005] 互不侵犯】【状压DP(含概念讲解)】
2022-08-02 15:28:00 【Eternity_GQM】
文章目录
什么是状压DP
状压 DP 是动态规划的一种,通过将状态压缩为整数来达到优化转移的目的。
如下图所示,可以用0/1表示状态,然后转换为十进制数进行存储,大大减少存储空间。
[SCOI2005] 互不侵犯
题目描述
在N×N
的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
输入格式
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式
所得的方案数
样例 #1
样例输入 #1
3 2
样例输出 #1
16
思路分析
数组f[i][st][j]
的定义,以及状态转移方程:
不合法检验:
行内不能相邻,行间要检验三位。
st 的范围(状态数组的大小):
代码
int n, k;
ll f[9][1 << 9][82], ans;
int c(int st){
//返回st的二进制中1的个数
int cnt = 0;
while(st){
if(st%2)
cnt++;
st /= 2;
}
return cnt;
}
bool check1(int st){
//同行检验
for (int i = 0; i < n - 1;i++)
if ((st & (1 << i)) && (st & (1 << (i + 1))))
return false;
return true;
}
bool check2(int st,int st2){
//与上一行的检验
for (int i = 0; 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;
}
void solve(){
cin >> n >> k;
for (int i = 0; i < n;i++){
for (int st = 0; st < (1 << n);st++){
if(!check1(st))
continue;
if (i == 0)
f[i][st][c(st)] = 1;
else{
for (int j = c(st); j <= k;j++){
for (int st2 = 0; st2 < (1 << n);st2++){
if(!check1(st2)||!check2(st,st2))
continue;
f[i][st][j] += f[i - 1][st2][j - c(st)];
}
}
}
}
}
for (int st = 0; st < (1 << n);st++)
ans += f[n - 1][st][k];
cout << ans << nl;
}
边栏推荐
猜你喜欢
随机推荐
继续来学习有关淘宝的API接口的使用——获得店铺的所有商品 API
uniapp 小程序 动态style class
RecSys'22 推荐系统论文梳理
不平衡问题: 深度神经网络训练之殇
23.支持向量机的使用
SIGIR'22 推荐系统论文之POI篇
类的比较大小(Comparable -> compareTo(类自己实现接口),Comparator -> compare(新建一个类作为比较器))
Basic management of system storage -- mounts, partitions, user quotas
最强分布式锁工具:Redisson
【深度学习】关于处理过拟合的一点心得
2.6 - 进程资源
CefSharp practical demonstration
VPP snort插件
CS5210的参数详情资料分享
2.3 - P、V、S机制
AI+BI+可视化,Sugar BI架构深度剖析
Idea中运行sparkSQL
8大软件供应链攻击事件概述
05-读写锁、阻塞队列及四组API、同步队列
Qt | 模态对话框和非模态对话框 QDialog