P1896 [SCOI2005] 互不侵犯 方法记录
[SCOI2005] 互不侵犯
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强(2018/4/25)
输入格式
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式
所得的方案数
样例 #1
样例输入 #1
3 2
样例输出 #1
16
审题
由题目可得:棋盘上国王割据的过程是随着“阶段”的增长,在每个状态维度上不断扩展的。在任意时刻,已经求出最优解的状态与尚未求出最优解的状态在各维度上的分界点组成了DP扩展的“轮廓”。而在这道题中,我们需要经济地保存棋盘的详细状态,所以想到状态压缩DP。
状态压缩DP介绍
以本题为例,假如有一行的国王放置状态如下

这里使用两个数组记录状态
sit[i]表示有无国王的二进制状态
sta[i]表示国王的个数
则如上图\(sit[i]=(100101)_2=37\),\(sta[i]=3\).
这样一来,一行中国王的状态就被压缩到一个维度中
推导转移方程
\(f[i][j][s]+=f[i-1][k][s-sta[j]]\)
其中,i表示第i行,j表示当前国王状态,s表示当前国王个数,结合sit[],sta[]表示。
预处理每一个状态
dfs(x,num,cur)元素含义:x表示递归的层数,num表示已经上场的国王数量,cur表示当前遍历到的位置(行)
点击查看代码
void dfs(int x,int num,int cur)//预处理每一个状态
{
if(cur>=n)//超出边界,处理完毕
{
sit[++cnt]=x;
sta[cnt]=num;
return ;
}
dfs(x,num,cur+1);//当前位置不放国王:国王数量不变,下一个位置可以放国王,故指向下一个位置
dfs(x+(1<<cur),num+1,cur+2);//当前位置放国王:国王数量+1,下一个位置不可以放国王,故指向下下个位置
}
判断冲突情况
知识点:位运算
点击查看代码
if(sit[j]&sit[x]) continue;//x:当前行位置国王放置情况;j:正上方位置国王放置情况。上下冲突
if((sit[j]<<1)&sit[x]) continue;//左上右下冲突
if(sit[j]&(sit[x]<<1)) continue;//右上左下冲突
以下为图示

程序大致框架:
输入->预处理->DP循环(判断冲突)->统计答案->输出。
完整带注释代码
点击查看代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
int sit[2000],sta[2000];
//sit[i]表示有无国王的二进制状态
//sta[i]表示国王的个数
int cnt=0;
int n,k;
long long f[10][2000][100]={0};
//dfs(x,num,cur)元素含义:x 递归的层数;num 已经上场的国王数量;cur当前遍历到的位置(行)
void dfs(int x,int num,int cur)//预处理每一个状态
{
if(cur>=n)//超出边界,处理完毕
{
sit[++cnt]=x;
sta[cnt]=num;
return ;
}
dfs(x,num,cur+1);//当前位置不放国王:国王数量不变,下一个位置可以放国王,故指向下一个位置
dfs(x+(1<<cur),num+1,cur+2);//当前位置放国王:国王数量+1,下一个位置不可以放国王,故指向下下个位置
}
//f[i][j][s]+=f[i-1][k][s-sta[j]]状态转移方程
//i=第i行;j=当前国王的状态;s=当前国王的个数,可以用sit[]sta[]表示
int main()
{
scanf("%d%d",&n,&k);
dfs(0,0,0);//预处理
for(int i=1;i<=cnt;i++)f[1][i][sta[i]]=1;//处理第一行:防止越界
for(int i=2;i<=n;i++)
for(int j=1;j<=cnt;j++)
for(int x=1;x<=cnt;x++)//x为j正下方的位置
{
if(sit[j]&sit[x]) continue;//x:当前行位置国王放置情况;j:正上方位置国王放置情况。上下冲突
if((sit[j]<<1)&sit[x]) continue;//左上右下冲突
if(sit[j]&(sit[x]<<1)) continue;//右上左下冲突
for(int s=sta[j];s<=k;s++)f[i][j][s]+=f[i-1][x][s-sta[j]];
}
long long ans=0;
for(int i=1;i<=cnt;i++)ans+=f[n][i][k];//n行矩阵,放置k个国王的情况总数
printf("%lld",ans);
return 0;
}
这个视频给我的理解带来极大的帮助
(而且声音很甜很好听)
https://www.bilibili.com/video/av681073078/?vd_source=b9e2e351c4ebc946cfd86808c70b65ce
P1896 [SCOI2005] 互不侵犯 方法记录的更多相关文章
- 洛谷 P1896 [SCOI2005]互不侵犯
洛谷 P1896 [SCOI2005]互不侵犯 题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8 ...
- 洛谷P1896 [SCOI2005]互不侵犯King
P1896 [SCOI2005]互不侵犯King 题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共 ...
- 洛谷——P1896 [SCOI2005]互不侵犯
P1896 [SCOI2005]互不侵犯 状压DP入门题 状压DP一般需要与处理状态是否合法,节省时间 设定状态dp[i][j][k]表示第i行第j个状态选择国王数为k的方案数 $dp[i][j][n ...
- 洛谷 P1896 [SCOI2005]互不侵犯 (状态压缩DP)
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...
- 洛谷 P1896 [SCOI2005]互不侵犯King
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入输出格式 输入格式: 只有一行,包 ...
- P1896 [SCOI2005]互不侵犯King
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入输出格式 输入格式: 只有一行,包 ...
- 洛谷P1896 [SCOI2005]互不侵犯King【状压DP】
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入格式: 只有一行,包含两个数N,K ...
- P1896 [SCOI2005]互不侵犯
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...
- 【题解】洛谷P1896 [SCOI2005] 互不侵犯(状压DP)
洛谷P1896:https://www.luogu.org/problemnew/show/P1896 前言 这是一道状压DP的经典题 原来已经做过了 但是快要NOIP 复习一波 关于一些位运算的知识 ...
随机推荐
- python常用功能模块
路径相关:os.pathlib Windows注册表相关:winreg 系统cpu.内存.线程相关:psutil 文件.文件夹处理:shutil 解析和生成ini文件:ConfigParser:(co ...
- CMake库搜索函数居然不搜索LD_LIBRARY_PATH
摘要: 本文通过编译后运行找不到库文件的问题引入,首先分析了find_package(JNI)的工作流程,而后针对cmake不搜索LD_LIBRARY_PATH的问题,提出了一种通用的解决办法. 本文 ...
- Auto.js 特殊定位控件方法 不能在ui线程执行阻塞操作,请使用setTimeout代替
本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! Auto.js 特殊定位控件方法 操作环 ...
- MySQL金融应用场景下跨数据中心的MGR架构方案(2)
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 如何在多个数据中心部署多套MGR集群,并实现故障快速切换. 上篇文章介绍了如何在多数据中心部署多套MGR集群,并构建集群间 ...
- DolphinScheduler 荣获 2021 中国开源云联盟优秀开源项目奖!
点击上方 蓝字关注我们 好消息,中国开源云联盟(China Open Source Cloud League,简称"COSCL")于近日公布 2021 杰出开源贡献者.优秀开源项目 ...
- java-Collection,List简单使用与方法/(集合使用-中)
1.1集合只存放引用类型的元素并且集合存放的时元素的引用(地址)1.2新循环遍历集合 Collection c = new ArrayList(); c.add("one"); c ...
- df空间满,du找不到文件的问题
最近看了一下问题: df -h Filesystem Size Used Avail Use% Mounted on rootfs 271G 267G 2.2G 100% / 根分区满了,du 找不到 ...
- Redis技术
Redis技术 Redis 简介 Redis 是一个 key-value 的 nosql 产品,存储的 value 类型更加丰富,包括 string(字符串), list(链表),set(集合),zs ...
- 小A的树 - 树形DP
题面 1 9 4 4 1 1 5 1 2 3 2 3 6 6 7 6 8 9 6 0 1 0 1 0 0 1 0 1 3 2 7 3 4 0 9 5 YES YES NO NO 题解 n <= ...
- 【java】学习路径29-异常捕捉实例
import java.util.ArrayList;public class ExceptionCatchDemo { public static void main(String[] args) ...