当前位置:网站首页>【[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;
}
边栏推荐
猜你喜欢
随机推荐
tiup mirror sign
Qt | 关于如何使用事件过滤器 eventFilter
不平衡之钥: 重加权法知几何
SQL查询数据以及排序
最强分布式锁工具:Redisson
QueryWrapper方法解释
Qt | 关于QPalette的使用
MySQL-2-设置权限-创建表
先睹为快!界面控件DevExpress WPF这些功能即将发布
CS5210的参数详情资料分享
form的编辑与展示的切换(输入框,单选多选框,上传图片,颜色选择器)适用个人信息的展示与修改
Qt | 关于容器类的一些总结
阿里巴巴《MySQL成长手册》精简版
性能测试详解(理论篇)
浅聊组合函数
Qt | 设置部件大小 sizeHint、minimumSizeHint、sizePolicy、stretch factor
Qt | QWidget 的一些总结
【个人总结】2022.7月结
【服务器数据恢复】Raid阵列更换故障硬盘后数据同步失败的数据恢复案例
数据防泄漏产品该如何选择