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 复习一波 关于一些位运算的知识 ...
随机推荐
- IO概述(概念&分类)和字节输入流+OUTputStream类&FileOutPutStream类介绍
IO概述 什么是IO 生活中,你肯定经历过这样的场景.当你编辑一个文本文件,忘记了保存,可能文件就白白编辑了.当你的电脑上插入一个U盘,可以吧一个视频,拷贝到你的电脑硬盘里,那么数据都是在哪些设备上的 ...
- nodejs学习总结01
主流渲染引擎介绍1.渲染引擎又叫 排版引擎 或 浏览器内核 .(双内核:执行html和css的)2,主流的渲染引擎有**Chrome浏览器**:Blink引壁(WebKit的一个分支)**Safari ...
- 用户认证(Authentication)进化之路:由Basic Auth到Oauth2再到jwt
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_98 用户认证是一个在web开发中亘古不变的话题,因为无论是什么系统,什么架构,什么平台,安全性是一个永远也绕不开的问题 在HTTP ...
- 6.14 YZBOI模拟赛solution
\(6.14\ YZBOI\)模拟赛\(solution\) 本来不想写题解来着...毕竟是自己找的题还是写一写吧 上午为了整活,就把赛制改成\(IOI\)赛制了,于是乎拯救了大家的\(70pts\) ...
- MySQL Shell无法拉起MGR集群解决办法
MySQL Shell无法拉起MGR集群解决办法 用MySQL Shell要重新拉起一个MGR集群时,可能会提示下面的错误信息: Dba.rebootClusterFromCompleteOutage ...
- Java基础 | Stream流原理与用法总结
Stream简化元素计算: 一.接口设计 从Java1.8开始提出了Stream流的概念,侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式:依旧先看核心接口的设计: BaseStream: ...
- B端产品需求分析与优先级判断
需求分析是产品经理工作中的重要一部分,而对B端产品经理来说,因为业务的特殊性,所以需求分析更考验产品经理的基础能力比如还原场景中业务调研的能力.需求价值分析中对价值的界定等. B端厂商的产品需求多数来 ...
- 架构与思维:互联网高性能Web架构
1 什么是高性能Web架构 在互联网业务中,我们经常会面临流量巨大的复杂的分布式场景.这就要求我们在设计系统的时候保证系统具有承载高并发(High Concurrency)的能力,同时能够保证系统的高 ...
- ARC125E - Snack (网络流)
题面 有 N N N 种糖果, M M M 个小孩子,第 i i i 种糖果有 A i A_i Ai 个,第 i i i 个孩子不能有超过 B i B_i Bi 个同种类型的糖果,第 i i i ...
- 【java】学习路线8-cmd带命令编译包
/*java类包(package)package XX.XX.XX; 包名命名规则:(以域名开头,都是小写) com.remooo.xx 编译:javac -d . ...