[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][ ...
随机推荐
- VC+++ 操作word
最近完成了一个使用VC++ 操作word生成扫描报告的功能,在这里将过程记录下来,开发环境为visual studio 2008 导入接口 首先在创建的MFC项目中引入word相关组件 右键点击 项目 ...
- DOM基础操作实战代码
对于已经讲解给大家的DOM实战,我今天给大家几个实战代码,可以让大家加深对此的理解! 1.用DOM动态生成这样一个结构: <div class=”example”> <p class ...
- html5 文档元素 header footer h1h2h4
文档元素: 用于在页面的大布局, 区分各个主体和概念. 让整体清晰, 元素有语义, 进一步代替div 具体划分图示: (参考) <hgroup> <section> <n ...
- 【element+vue后台页面】Vue-element-admin
https://segmentfault.com/a/1190000009275424
- 很赞的一个教程: React.js 小书
很赞, React.js 小书 http://huziketang.com/books/react/ 推荐阅读入门, 照着来一遍,能会个七七八八, 更多的还需要多写 import Re ...
- LeetCode赛题395----Longest Substring with At Least K Repeating Characters
395. Longest Substring with At least K Repeating Characters Find the length of the longest substring ...
- Python爬虫教程-09-error 模块
Python爬虫教程-09-error模块 今天的主角是error,爬取的时候,很容易出现错,所以我们要在代码里做一些,常见错误的处,关于urllib.error URLError URLError ...
- 微信小程序开发10-开发流程
1.Flex布局 Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性.任何一个容器都可以指定为Flex布局. 2.设置容器,用于统一管理容器内项目布局,也就是管 ...
- DHCP服务搭建
DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP ...
- linux安装redis+RedisDesktopManager
一:redis简介 (REmote DIctionary Server Redis远程字典服务器) 1:Redis是一个开源的使用ANSI C语言编写.完全免费开源的,遵守BSD协议.支持 ...