[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][ ...
随机推荐
- [POI2007]EGZ-Driving Exam
能到达所有路的充要条件是能到达左右两端的路 用vector反向建边对每条路左右分别求个最长不上升子序列 预处理出每条路向左向右分别需要多建多少路才能到达最左端和最右端 然后跑个\(\Theta(n)\ ...
- UOJ42. 【清华集训2014】Sum
传送门 Sol \((-1)^a=1-2(a~mod~2)=1-2a+4\lfloor\frac{a}{2}\rfloor\) 那么原式变成 \(n-2\sum_{i=1}^{n}\lfloor d\ ...
- 浅谈 Underscore.js 中 _.throttle 和 _.debounce 的差异[转]
看的文章来自: https://blog.coding.net/blog/the-difference-between-throttle-and-debounce-in-underscorejs 使用 ...
- LeetCode赛题390----Elimination Game
# 390. Elimination Game There is a list of sorted integers from 1 to n. Starting from left to right, ...
- 简析 Tomcat 、Nginx 与 Apache 的区别
简析 Tomcat .Nginx 与 Apache 的区别 本文讲的是简析 Tomcat .Nginx 与Apache的区别, 经常在用 apache 和 tomcat 等这些服务器,可是总感觉还是不 ...
- java.lang.IllegalArgumentException: XML fragments parsed from previous mappers does not contain value for
使用mybatis做一个简单的查询的时候,报了这个问题.代码如下: <mapper namespace="cn.gaiay.business.zm.live.living.dao.Li ...
- Java多线程学习笔记(三)同步和异步
首先是一段代码: public class HasSelfPrivateNum { public void addI(String username){ try { int num=0; if(use ...
- maven(15),快照与发布,RELEASE与SNAPSHOT
发布RELEASE 用户A将代码打包发布到RELEASE仓库,具体操作参考上篇文章.用户B使用时,需要在pom.xml添加JAR包的依赖坐标.如果用户A将版本从1.0升级为2.0,用户B使用时也 ...
- JpaRepository 查询规范
1.JpaRepository支持接口规范方法名查询.意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现,目前支持的关键字如下. Keyword Sample JPQL snippet ...
- EF学习之CodeFirst(一)--创建Model
一.创建Model 创建Model类有两种方式: 1.直接创建model 所有约束条件都以特性的方式写在model的属性上面,映射到数据库的table表名标识在class上,例如: [Table(&q ...