[SCOI2005]互不侵犯(状压DP)
嗝算是状压DP的经典题了
#\(\mathcal{\color{red}{Description}}\)
在\(N×N\)的棋盘里面放\(K\)个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共\(8\)个格子。
#\(\mathcal{\color{red}{Solution}}\)
嗯,然后今天(其实是前天)接触了一种新颖的\(DP\)——状压\(DP\)。其实就是一种借用二进制表示状态的方式,类似于“压缩”了一样。譬如说我需要马上得到一张01图上,某一行的状态,那我们就可以用二进制数来表示:$$100010_{(2)} = 34_{(10)}$$那么,对于这一行的状态,我们就可以用\(34\)这个数记录,而不是用数组来记录——瞬间减少了一维是不是?但其实还有更多的方便之处,比如说我们在\(DP\)的单次转移时,有时需要用到一整行的状态,用数组记录的话不便于转移,我们就需要用二进制来转移。
哦,还有,一般情况下状压之后都是倒着存的,因为这符合二进制的定义规则,比如我的一行的状态如此$$110101$$那么二进制下应该是$$101011$$可以类比一下,从左至右列标逐渐增大,但是二进制位从左到右权值逐渐减小。为了防止出现什么麻烦事儿,所以就倒着存了\(qwq\)。
嗯,那么它方便的地方在哪里呢?就是我们可以像访问数组的一行一样,甚至更快速的访问,比如:$$(1 << k - 1) & s$$可以询问状态\(s\)的第\(k\)位上是\(1\)是\(0\),$$(j >> k)<<k$$表示把状态\(j\)的二进制表示下最右边几位清零(你看数组就不能做直接清零)。
那对于这个题而言,1表示有我们用\(dp_{i,j,k}\)表示前\(i\)行,第\(i\)行状态是二进制表示(十进制下的值)为\(j\),放置了\(k\)个国王的方案数,那么状态转移方程就是$$dp_{i,j,k} = \sum dp_{i - 1, new, k - getlen(j)}$$
其中\(new\)表示我们所枚举的上一行的所有合法状态,\(getlen(j)\)表示\(j\)状态有多少位为\(1\),因为我们所定义的\(1\)即为放了国王。
其实好像对于一部分的东西是可以预处理出来的,但那时我偷了个懒,直接算的\(qwq\)
#include <cstdio>
#include <iostream>
#define ll long long
using namespace std ;
ll dp[20][210][1026], ans ;
int N, K, NN, i, j, k, l, L ;
inline int _get(ll x){
int ret = 0 ;
while(x){
if(x & 1) ret ++ ;
x >>= 1 ;
} return ret ;
}
inline bool check(ll x, ll y){
if(x & y) return 1 ;
if( (x << 1) & y) return 1 ;
if( (x >> 1) & y) return 1 ;
if( (y >> 1) & y) return 1 ;
return 0 ;
}
int main(){
cin >> N >> K ;
dp[0][0][0] = 1, NN = (1 << N) - 1 ;
for(i = 1; i <= N; i ++)
for(j = 0; j <= K; j ++)
for(k = 0; k <= NN; k ++){
L = _get(k) ;
if(L > j) continue ;
if(k & (k >> 1)) continue ;
for(l = 0; l <= NN; l ++){
if(check(k ,l)) continue ;
dp[i][j][k] += dp[i - 1][j - L][l] ;
}
}
for(i = 0 ; i <= NN; i ++ ){
ans += dp[N][K][i] ;
}
cout << ans ;
}
[SCOI2005]互不侵犯(状压DP)的更多相关文章
- BZOJ1087[SCOI2005]互不侵犯——状压DP
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入 只有一行,包含两个数N,K ( ...
- P1896 [SCOI2005]互不侵犯 状压dp
正解:状压dp 解题报告: 看到是四川省选的时候我心里慌得一批TT然后看到难度之后放下心来觉得大概没有那么难 事实证明我还是too young too simple了QAQ难到爆炸TT我本来还想刚一道 ...
- SCOI2005 互不侵犯 [状压dp]
题目传送门 题目大意:有n*n个格子,你需要放置k个国王使得它们无法互相攻击,每个国王的攻击范围为上下左走,左上右上左下右下,共8个格子,求最多的方法数 看到题目,是不是一下子就想到了玉米田那道题,如 ...
- [SCOI2005]互不侵犯 (状压$dp$)
题目链接 Solution 状压 \(dp\) . \(f[i][j][k]\) 代表前 \(i\) 列中 , 已经安置 \(j\) 位国王,且最后一位状态为 \(k\) . 然后就可以很轻松的转移了 ...
- luogu1896 [SCOI2005]互不侵犯 状压DP
题目大意 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子.( 1 <=N <=9, 0 ...
- NOI P1896 互不侵犯 状压DP
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...
- _bzoj1087 [SCOI2005]互不侵犯King【dp】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1087 令f(i, j, k)表示前i列,二进制状态为j,已经用了k个国王的方案数,则 f(i ...
- 洛谷——P1896 [SCOI2005]互不侵犯
P1896 [SCOI2005]互不侵犯 状压DP入门题 状压DP一般需要与处理状态是否合法,节省时间 设定状态dp[i][j][k]表示第i行第j个状态选择国王数为k的方案数 $dp[i][j][n ...
- 状压DP概念 及例题(洛谷 P1896 互不侵犯)
状压DP 就是状态压缩DP.所谓状态压缩,就是将一些复杂的状态压缩起来,一般来说是压缩为一个二进制数,用01来表示某一元素的状态. 比如一排灯泡(5个) 我们可以用一串二进制01串来表示他们的状态 1 ...
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
随机推荐
- csharp: using wininet.dll
/// <summary> /// Windows Embedded CE 6.0 R3 WinInet Functions /// https://technet.microsoft.c ...
- css,js移动资源
随着移动市场的逐步扩大及相关技术的日趋完善,对前端开发提出了新的岗位要求,在继承前人成果的基础上需要在新的历史条件下有新的创新.移动端的开发,虽然没有IE6众多问题的折磨,但是多平台,多设备的兼容,也 ...
- 【PyQt5 学习记录】001:第一个界面
PyQt5 的安装很简单: pip3 install PyQt5 然后就是写一个最简单的界面试试手: import sys from PyQt5.QtWidgets import QApplicati ...
- h5的classList对象
H5新增属性classList h5中新增了一个classList,原生js可以通过它来判断获取dom节点有无某个class. classList是html元素对象的成员,它的使用非常简单,比如 co ...
- git忽略相应文件夹,不上传
1.在项目根目录里 右键选择Git Bash 进入命令行 2. touch .gitignore ,生成“.gitignore”文件. 3. .gitignore文件里输入以下内容.DS_Stor ...
- jquery实现除指定区域外点击任何地方隐藏DIV
<!--弹出的表情选择框--> <div class="layui-input-block expression-box"> </div> &l ...
- Java内存模型(JMM)以及 垃圾回收机制 小结
内存模型: 内存模型描述了程序中各个变量(实例域.静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节,对象最终是存储在内存里面的,这点没有错,但是编译 ...
- 【转】PHP如何快速读取大文件
在PHP中,对于文件的读取时,最快捷的方式莫过于使用一些诸如file.file_get_contents之类的函数,简简单单的几行代码就能 很漂亮的完成我们所需要的功能.但当所操作的文件是一个比较大的 ...
- 2.MySQL 数据类型
MySQL 数据类型 MySQL中定义数据字段的类型对你数据库的优化是非常重要的. MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型. 数值类型 MySQL支持所有标准S ...
- linux 下通过过 hbase 的Java api 操作hbase
hbase版本:0.98.5 hadoop版本:1.2.1 使用自带的zk 本文的内容是在集群中创建java项目调用api来操作hbase,主要涉及对hbase的创建表格,删除表格,插入数据,删除数据 ...