原题链接

[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] 互不侵犯 方法记录的更多相关文章

  1. 洛谷 P1896 [SCOI2005]互不侵犯

    洛谷 P1896 [SCOI2005]互不侵犯 题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8 ...

  2. 洛谷P1896 [SCOI2005]互不侵犯King

    P1896 [SCOI2005]互不侵犯King 题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共 ...

  3. 洛谷——P1896 [SCOI2005]互不侵犯

    P1896 [SCOI2005]互不侵犯 状压DP入门题 状压DP一般需要与处理状态是否合法,节省时间 设定状态dp[i][j][k]表示第i行第j个状态选择国王数为k的方案数 $dp[i][j][n ...

  4. 洛谷 P1896 [SCOI2005]互不侵犯 (状态压缩DP)

    题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...

  5. 洛谷 P1896 [SCOI2005]互不侵犯King

    题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入输出格式 输入格式: 只有一行,包 ...

  6. P1896 [SCOI2005]互不侵犯King

    题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入输出格式 输入格式: 只有一行,包 ...

  7. 洛谷P1896 [SCOI2005]互不侵犯King【状压DP】

    题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入格式: 只有一行,包含两个数N,K ...

  8. P1896 [SCOI2005]互不侵犯

    题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...

  9. 【题解】洛谷P1896 [SCOI2005] 互不侵犯(状压DP)

    洛谷P1896:https://www.luogu.org/problemnew/show/P1896 前言 这是一道状压DP的经典题 原来已经做过了 但是快要NOIP 复习一波 关于一些位运算的知识 ...

随机推荐

  1. 实践GoF的23种设计模式:观察者模式

    摘要:当你需要监听某个状态的变更,且在状态变更时通知到监听者,用观察者模式吧. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:观察者模式>,作者: 元闰子 . 简介 现在有 ...

  2. 1269: 求最长上升子序列(LIS)

     题目描述: LIS问题(longest increasing subsequence),即:最长上升子序列问题,是动态规划中一个比较经典的问题.具体描述为:一个有n个整数的序列:A[1],A[2], ...

  3. 搞懂前端二进制系列(一):🍇 认识Blob对象

    参考资料: https://juejin.cn/post/6844904183661854727 [你不知道的Blob] https://juejin.cn/post/6844904144453517 ...

  4. python 日志类

    简介 在所有项目中必不可少的一定是日志记录系统,python为我们提供了一个比较方便的日志模块logging,通常,我们都会基于此模块编写一个日志记录类,方便将项目中的日志记录到文件中. loggin ...

  5. 【AGC】增长服务1-远程配置示例

    ​ [AGC]增长服务1-远程配置示例 前言:上一次笔者给大家带来了AGC领域的性能管理服务的学习.这次我们再继续深化学习AGC的相关知识.在文章开始之前,再给读者简单介绍一下AGC,以免第一次来的读 ...

  6. BZOJ1787/Luogu4281: [Ahoi2008]Meet 紧急集合

    画画图可知,三点\(lca\)必有两相同,\(a,b,c\)距离为\(dis_a + dis_b + dis_c - dis_{lca(a,b)} - dis_{lca(b,c)} - dis_{lc ...

  7. Redis 03 字符串

    参考源 https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0 版本 本文章基于 Redis 6.2.6 应用场景:计数 ...

  8. java-RandomAccessFile操作以及IO流简单使用

    1.1RandomAccessFile--使用RAF读写基本类型数据,以及了解Raf的指针操作 write有相对应的写入基本类型的方法 void seek(Long pos)调整RAF指针位置,可以在 ...

  9. Spring Boot部署方法

    Spring Boot部署方法     网上搜到的部署方法无非是打成jar包,然后shell执行nohup java调用jar命令,或者是打成war包然后部署到tomcat或者jetty容器上面. S ...

  10. No value specified for parameter 5异常

    No value specified for parameter 5 翻译:没有为参数5指定值 在sql语句中,有5个" ? "号,但是赋值的时候只赋了前面4个" ?&q ...