状压DP(超详细!!!)
一、定义
总述
状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式。
很多棋盘问题都运用到了状压,同时,状压也很经常和BFS及DP连用。
状压dp其实就是将状态压缩成2进制来保存 其特征就是看起来有点像搜索,每个格子的状态只有1或0 ,是另一类非常典型的动态规划
举个例子:有一个大小为n*n的农田,我们可以在任意处种田,现在来描述一下某一行的某种状态:
设n = 9;
有二进制数 100011011(九位),每一位表示该农田是否被占用,1表示用了,0表示没用,这样一种状态就被我们表示出来了:见下表
所以我们最多只需要 2^(n + 1) - 1的十进制数就好(二进制形式是n个1) 现在我们有了表示状态的方法,但心里也会有些不安:上面用十进制表示二进制的数,枚举了全部的状态,DP起来复杂度岂不是很大?没错,状压其实是一种很暴力的算法,因为他需要遍历每个状态,所以将会出现2^n的情况数量,不过这并不代表这种方法不适用:一些题目可以依照题意,排除不合法的方案,使一行的总方案数大大减少从而减少枚举
为了更好的理解状压dp,首先介绍位运算相关的知识。
- ’&’符号,x&y,会将两个十进制数在二进制下进行与运算(都1为1,其余为0) 然后返回其十进制下的值。例如3(11)&2(10)=2(10)。
- ’|’符号,x|y,会将两个十进制数在二进制下进行或运算(都0为0,其余为1) 然后返回其十进制下的值。例如3(11)|2(10)=3(11)。
- ’^’符号,x^y,会将两个十进制数在二进制下进行异或运算(不同为1,其余 为0)然后返回其十进制下的值。例如3(11)^2(10)=1(01)。
- ’~’符号,~x,按位取反。例如~101=010。
- ’<<’符号,左移操作,x<<2,将x在二进制下的每一位向左移动两位,最右边用0填充,x<<2相当于让x乘以4。 ’>>’符号,是右移操作,x>>1相当于给x/2,去掉x二进制下的最右一位
1.判断一个数字x二进制下第i位是不是等于1。(最低第1位)
方法:if(((1<<(i−1))&x)>0) 将1左移i-1位,相当于制造了一个只有第i位 上是1,其他位上都是0的二进制数。然后与x做与运算,如果结果>0, 说明x第i位上是1,反之则是0。
2.将一个数字x二进制下第i位更改成1。
方法:x=x|(1<<(i−1)) 证明方法与1类似。
3.将一个数字x二进制下第i位更改成0。
方法:x=x&~(1<<(i−1))
4.把一个数字二进制下最靠右的第一个1去掉。
方法:x=x&(x−1)
二、典型例题
【例题1】骑士(P1896 [SCOI2005]互不侵犯)
题目描述
在 n×n(1<=n<=10) 的棋盘上放 k(0<=k<n×n)个国王,国王可攻击相邻的 8 个格子,求使它们无法互相攻击的方案总数。
输入格式
输入有多组方案,每组数据只有一行,包含两个整数 n 和 k。
输出格式
每组数据一行为方案总数,若不能够放置则输出 0。
输入样例
3 2
4 4
样例输出
16
79
实际状压dp顾名思义,就是采用位运算,来记录更多的必须记录的状态来做dp有了比较深的dp功底后只要对位运算有了解就可以解决问题。。。
考虑到每行每列之间都有互相的约束关系。因此,我们可以用行和列作为另一个状态的部分。用一个新的方法表示行和列的状态:数字。考虑任何一个十进制数都可以转化成一个二进制数,而一行的状态就可以表示成这样——例如:1010(2)
就表示:这一行的第一个格子没有国王,第二个格子放了国王,第三个格子没有放国王,第四个格子放了国王。而这个二进制下的数就可以转化成十进制: 10(10)
于是,我们的三个状态就有了:第几行(用i表示)、此行放什么状态(用j表示)、包括这一行已经使用了的国王数(用s表示)。
考虑状态转移方程。我们预先处理出每一个状态(s[x])其中包含二进制下1的个数,及此状态下这一行放的国王个数(num[x]),于是就有:
f[i][j][s]=sum(f[i−1][k][s−num[j]]),f[i][j][s]就表示在只考虑前i行时,在前i行(包括第i行)有且仅有s个国王,且第i行国王的情况是编号为j的状态时情况的总数。而k就代表第i-1行的国王情况的状态编号
【例题2】牧场的安排(P1879 [USACO06NOV]玉米田Corn Fields)
Farmer John 新买了一块长方形的牧场,这块牧场被划分成 M列 N 行 (1≤M≤12;1≤N≤12),每一格都是一块正方形的土地。FJ 打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用。遗憾的是,有些土地相当的贫瘠,不能用来放牧。并且,奶牛们喜欢独占一块草地,于是 FJ 不会选择两块相邻的土地,即:没有哪两块草地有公共边。当然,FJ 还没有决定在哪些土地上种草。 作为一个好奇的农场主,FJ 想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择。当然,把新的牧场荒废,不在任何土地上种草,也算一种方案。请你帮 FJ 算一下这个总方案数。
输入格式
第 1行:两个正整数 M 和 N,用空格隔开;第 2到 M+1行:每行包含 N 个用空格隔开的整数,描述了每块土地的状态。输入的第 i+1行描述了第 i行的土地。所有整数均为 0 或 1,1 表示这块土地足够肥沃,0 则表示这块地上不适合种草。
输出格式
第 1 行:输出一个整数,即牧场分配总方案数除以 10^8的余数。
样例输入
2 3
1 1 1
0 1 0
样例输出
9
题目大意
给N*M的棋盘,每个格子不是0就是1,1代表可以种草,否则不能。相邻两个格子不能同时种草,求种草的方案总数。
思路
状态压缩类动态规划,状压dp一般会有明显的数据范围特征,即n,m一般都在20以内。可将每一排的N个看成一个N位二进制,先预处理出每一行可以运行的状态,这样可以去掉很多无效状态(如110),然后DP处理,枚举当前有效状态和上一行有效状态的关系。
f[i][j] 表示第i行在状态j的时候的方案数,其中j我们用一个二进制数来表示。
转移的时候只要判断与当前行和上一行是否冲突即可,如果不冲突,分f[i][j]=∑f[i−1][k]其中k为不冲突的状态。Ans=∑1≤i≤numf[n][i] 就是最后的答案(num为状态总数)。
初始条件:f[1][i]=1 (1<=i<=a[1].num).
状压DP(超详细!!!)的更多相关文章
- 浅说——状压DP
第一次没认真听,没听懂.(有点难) 第二次才搞懂,主要位运算太烦了!!! 位运算基础知识: 名称 符号 规则 按位与 & 全一则一,否则为零 按位或 | 有一则一,否则为零 按位取反 ~ 是零 ...
- 【状压DP】bzoj1087 互不侵犯king
一.题目 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上.下.左.右,以及左上.左下.右上.右下八个方向上附近的各一个格子,共8个格子. I ...
- CF453B Little Pony and Harmony Chest (状压DP)
CF453B CF454D Codeforces Round #259 (Div. 2) D Codeforces Round #259 (Div. 1) B D. Little Pony and H ...
- poj3254 Corn Fields (状压DP)
http://poj.org/problem?id=3254 Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissio ...
- LightOJ1018 Brush (IV)(状压DP)
题目大概说一个平面有n个灰尘,可以用一把刷子直直刷过去清理直线上的所有灰尘,问最少要刷几下才能清理完所有灰尘. 首先怎么刷其实是可以确定的,或者说直线有哪些是可以确定的,而最多就有C(n,2)条不一样 ...
- hdu 3254 (状压DP) Corn Fields
poj 3254 n乘m的矩阵,1表示这块区域可以放牛,0,表示不能,而且不能在相邻的(包括上下相邻)两个区域放牛,问有多少种放牛的方法,全部不放也是一种方法. 对于每块可以放牛的区域,有放或者不放两 ...
- ZOJ1100 状压DP +深搜
记得做过类似于这类题目是能够用组合数学方法来解决的,可惜淡忘了,也找不到了,看了网上的也有人提到过能够用组合公式解决,但是没人做,都是用了状压DP的方法,这个状压非常难讲清楚吧,推荐两篇 第一遍大体看 ...
- hdu_1074_Doing Homework(状压DP)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1074 题意:给你n个课程(n<=15)每个课程有限制的期限和完成该课程的时间,如果超出时间,每超 ...
- hdu 3247 AC自动+状压dp+bfs处理
Resource Archiver Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 100000/100000 K (Java/Ot ...
随机推荐
- border和outline的区别
如果有一个需求,给一个元素增加一条边框,想必大家会习惯且娴熟的使用border来实现,我也是这样 但其实outline也能达到同样的效果,并且在有些场景下会更适用,比如下面的demo 使用bord ...
- laravel报错:SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '0' for key 'PRIMARY' (SQL: insert into `cart` (`uid`, `gid`, `gname`, `price`) values (3, 21, 夏季日系复古工装短袖衬衫男士印花潮流宽松五分
原因:要操作的数据表id没有设置自增,导致出现id为0的情况 解决方法:给该数据表的id字段设置自增
- 小程序开发笔记(八)—Js数组按日期分组显示数据
数据分组展示有两种方式,一种是后端直接传入分组格式的Json数据,另一种是我们在前端自己转换格式,这里我们在前端处理转换按日期分组的数据格式 1.例如后端返回数据格式为: [{createtime:' ...
- kali渗透综合靶机(十八)--FourAndSix2靶机
kali渗透综合靶机(十八)--FourAndSix2靶机 靶机下载地址:https://download.vulnhub.com/fourandsix/FourAndSix2.ova 一.主机发现 ...
- Java匹马行天下之学编程的起点——走进编程的殿堂
学编程的起点——走进编程的殿堂 前言: 知其然,知其所以然,努力固然重要,但是思维的提升会让你事半功倍,我会用我花费时间换来的“思维”带更多的朋友入门,让你们明明白白学编程,学编程,不迷茫. 转变思维 ...
- Servlet中实现多个功能案例
如何实现一个Servlet中的多个功能 前言:唉,打脸了,前脚刚说过要跟Servlet正式告别,后脚这不又来了,哈哈,总结出一点东西,纠结了一下还是做个分享吧,学习知识比面子重要,对吧,下回再也不约S ...
- asp.net发布后其他电脑部署——未能加载文件或程序集 System.Web.Mvc, Version=2.0.0.0, Culture=neutral,
本机测试及发布使用正常 在项目中添加了引用但相关dll文件未在bin文件夹中 导致发布后部署其他电脑未能加载程序集 网上说要下载相关内容在部署服务器安装 但怕在服务器安装出现其他问题 所以在项目中重新 ...
- 避免HBase PageFilter踩坑,这几点你必须要清楚
有这样一个场景,在HBase中需要分页查询,同时根据某一列的值进行过滤. 不同于RDBMS天然支持分页查询,HBase要进行分页必须由自己实现.据我了解的,目前有两种方案, 一是<HBase权威 ...
- DevExpress的分隔条控件SplitterControl的使用
场景 Winform控件-DevExpress18下载安装注册以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1 ...
- 第七篇Scrum冲刺博客
第七篇Scrum冲刺博客 一.站立式会议 提供当天站立式会议照片一张 二.每个人的工作 成员 已完成工作 明天计划完成的工作 遇到的困难 林剑峰 加入搜索页面 无 陆君健 校园卡匹配功能的实现 无 石 ...