状态压缩dp

状态压缩是设计dp状态的一种方式。
当普通的dp状态维数很多(或者说维数与输入数据有关),但每一维总
量很少是,可以将多维状态压缩为一维来记录。
这种题目最明显的特征就是: 都存在某一给定信息的范围非常小(在20
以内),而我们在dp中所谓压缩的就是这一信息。
(或者是在做题过程中分析出了某一信息种类数很少)
我们来看个例子

经典题

给出一个n*m的棋盘,要放上一些棋子,要求不能有任意两个棋子相邻。
求方案数。
n<=100;
m<=8。

设\(dp[i][s]\) 表示第i行的状态 s是这一行棋子的排列压缩而成的二进制数,1表示有棋子,0表示没有棋子;

转移:\(dp[i][s]=\sum_{s'}dp[i-1][s']|s\& s'=0\)

我们发现这个m是非常小的,这样就可以启发我们对每一行2^m状态压缩。
设dp[i][S]表示到了第i行,第i行的状态是S的方案数是多少。
其中S的第j位为1,表示i这行第j位放了一个棋子。
状态转移:\(dp[i][S]=\sum_{S\&S'==0}{dp[i-1][ S' ]}\)。
你会发现这样记录很暴力,状态数是与m相关的指数级的,但同时也就是因为m小我们就确实可以这么做。
这也正好映照了之前的:

其实本质就是很暴力的记录状态,只不过利用了题目本身的特殊条件(这一维很小),使得我们并不会因此复杂度过高。
同时也就是说,如果题目本身没有这样一个较小的信息,就不能应用状态压缩。
所以在接下来的题目中大家可以更注意一下题目所给的条件。
状态压缩dp肯定是有一维是指数级的,这正是状态压缩的特点。

BZOJ1087 互不侵犯

在n*n的棋盘上放置k个国王,使得任意两个国王互相不攻击。一个国王可以攻击到周围八个格子。
求放置方案数。
n<=9

\(dp[i][j][s]\)表示第i行s状态,之前放了j个国王的方案数;

\(dp[i][j+cnt(s)][s]=\sum_{(s'|(s'<<1)|(s'>>1))\&s==0}dp[i-1][j][s']\)

状态s与状态s'的转移:进行左移和右移。&3次,分别为不变,左移,右移;

更简单的思路(s|(s<<1)|(s>>1))&s'==0;

时间复杂度 \(O(n^3*状态数^2)<O(n^3*2^(2n))\)

位运算

1、 (s & (1 << i)):判断第 i 位是否是 1;
2、 s =s|(1<<i):把第 i 位设置成 1;
3、 s =s&(~(1<<i)):把第 i 位设置成 0;
(~:是按位取反,包括符号位)
4、 s =s^(1<<i) :把第 i 位的值取反;
5、 s =s & (s – 1):把一个数字 s 二进制下最靠右的第一个 1 去掉;
6、 for (s0 = s; s0; s0 = (s0 - 1) & s): 依次枚举 s 的子集;

复杂度: 对于一个共有n位有k个1的二进制数s,它的子集的个数\(C_n^k\)

那么对于1~n的所有情况:ans=\(\sum\limits_{k=0}^nC_n^k*2^k*1^{n-k}=(1+2)^n\)二项式定理

\(2^k\)表示k个1的所有可能情况

7: x&-x 取出x最低位的1。

拓扑序个数问题

给你一张拓扑图,求这张拓扑图有多少种不同的拓扑序.
n<=20。

dp[s]表示当前s集合中的点都已经在拓扑序中的方案数

转移考虑枚举下一个点选什么,下一个选的点要满足它在s中的点选完后的入度为0,也就是指向它的点都已经加进拓扑序(状态s)里了,转移到dp[s|(1<<i-1)] 。

处理一个数组in[u]表示其他哪个点指向u,然后转移的话就是保证s&in[u]=in[u];

bzoj2734

给定n,问集合{1,2,3,…,n}有多少个子集满足:若x在集合内,则2x和3x不在集合内。
n<=100000

\(q*2^x*2^y\)

记g[x]表示将x中的2,3因子去除后得到的值 (即q),记g[x]表示将x中的2,3因子去除后得到的值,若g[x]!=g[y],那么x与y互不影响。对于互相有影响的一组数,一定能表示成q2^a^ 3^b^(q为常数)。对每种q分别求解,再相乘即可。

打表:

\(1 \ \ \ \ \ \ 3^1 \ \ \ \ \ \ \ 3^2 \ \ \ \ \ \ \ 3^3\)

\(2^1 \ \ \ \ \ 2^1*3^1 \ \ \ \ \ 2^1*3^2 \ \ \ \ \ 2^13^3\)

\(2^2 \ \ \ \ \ 2^2*3^1 \ \ \ \ \ 2^2*3^2 \ \ \ \ \ 2^2*3^3\)

\(2^3 \ \ \ \ \ 2^3*3^1 \ \ \ \ \ 2^3*3^2 \ \ \ \ \ 2^3*3^3\)

显然向右和向下会冲突,也就是右和下会互相冲突

时间复杂度分析:一行一行来看,因为最大n<=100000 ,那我们3最多大约是3^10^,因此共有11个状态0~10;所以s开11位?就可以了,时间复杂度约为f[11]*f[10]其中f[i]表示斐波那契数列第i项,转移啥的和t1很像。

NOIP2016 愤怒的小鸟

平面上有n头猪,每次可以从(0,0)出发发射一只沿抛物线(y=ax^2^+bx)飞行的小鸟,可以消灭所有在飞行路线上的猪。
问消灭所有猪至少要几只小鸟。
n<=18

两头猪加上原点即可确定抛物线,于是不同的抛物线只有O(n^2)种。

start:

确定抛物线:

猪的数量不是很多,每一条抛物线至少要打到一只猪,所以可以枚举出所有可行的抛物线,这条抛物线对每一只猪能/不能打下来用一个二进制为表示。

当然只能打到1只猪的抛物线不用枚举,一开始就加进去它的表示就行。

枚举两只猪,如果它们不在同一列,则将它们的坐标x,y分别代入方程y=ax^2^+bx,解得a,b,如果这组a,b没找到过且a为负,则用这组a,b尝试对每一只猪尝试看能不能打到(计算横坐标对应纵坐标)。

假设当前状态为i,抛物线为第j条,抛物线打掉的小猪状态为para[j],那么有:

\(dp[i|para[j]]=min(dp[i|para[j]],dp[i]+1)\)

end.

start‘

设f[S]为已经消灭的猪的集合为S时的最少次数,暴力的转移方法为依次枚举抛物线去更新所有f,这样做时间复杂度为O(n^2^*2^n^)。

更快的转移方法为从小到大枚举S,每次打掉编号最小的还没消灭的猪,由于包含该猪的抛物线只有O(n)种,所以时间复杂度为O(n*2^n^)。

第i个抛物线:t[i]表示这条抛物线能消灭的猪是哪几只

dp[s]集合s中所有点都被消灭的最少抛物线条数;

在打0只小猪的时候,需要用0只小鸟,于是有:

dp[0]=0

dp[s]=min~i~{dp[s^t[i]]+1|t[i]&s=t[i],且t[i]包含s最低位}

首先s^t[i]表示没打这一坨小猪时的最小值,然后因为上面为了更快的算出来,所以我们要保证每次都要打掉编号最小的猪,然后找到所有状态中最小的吖+1,就是dp[s]的值w;

poj2923

有 n 个货物,并且知道了每个货物的重量,每次用载重量分别为c1,c2的火车装载,问最少需要运送多少次可以将货物运完。
N<=17

dp[s]表示s集合被c1,c2运走至少需要几次;

先处理出可以一次运走的情况,然后转移, 枚举子集:

dp[s]=min~t~{dp[s^t]+1|t&s=t};

找出所有状态(1.....(1<<n)-1)中选出可以用两辆车一次运完的状态(枚举全部)

把每个状态都看作一个物品,重量为该状态的总重量,价值为 1,其实我们就是求最少选几个不相交的集合能够覆盖全集。
求解 01 背包, dp[(1<<n)-1]为最优解。

转移方程: dp[s]=min(dp[s],dp[s^t]+1) 其中t集合内的元素可以被一次运完。
这个复杂度是O(3^n)。
实际上如果我们固定t集合包含s最低位的1,这样能避免重复运算,复杂度降约为O(3^(n-1))

Bzoj3900

动物园里有 n 头麋鹿。每头麋鹿有两支茸角,每支茸角有一个重量。然而,一旦某头麋鹿上两支茸角的重量之差过大,这头麋鹿就会失去平衡摔倒。为了不然这种悲剧发生,动物园院长决定交换某些茸角,使得任意一头麋鹿的两角重量差不超过 c。然而,交换两支茸角十分麻烦,不仅因为茸角需要多个人来搬运,而且会给麋鹿造成痛苦。因此,你需要计算出最少交换次数,使得任意一头麋鹿的两角重量差不超过 c。
注意,交换两支茸角只能在两头麋鹿之间进行。因为交换同一头麋鹿的两支角是没有意义的。
对于 100% 的数据, n <= 16, c <= 1000000, 每支茸角重量不超过1000000。

将所有鹿角排序,然后相邻两个做匹配,看相邻两个是否相差<=c;

设f[s]表示s这个集合的麋鹿,最少交换多少次可以使其合法;上界:f[s]=(cnt(s)-1)or inf;

f[s]=min~s'∈s~{f[s']+f[s^s']};​

Hdu3001放松题

现在有一个具有n个顶点和m条边的无向图(每条边都有一个距离权值),小明可以从任意的顶点出发,他想走过所有的顶点而且要求走的总距离最小,并且他要求过程中走过任何一个点的次数不超过2次。
1<=n<=10

\(dp[s][u]\)当前在u点,s状态第j位为0没有经过,为1经过1次,为2经过两次;

枚举下一个点v走哪里;

\(dp[s+(1<<v)][v]=min \{dp[s][u]+len[u][v]\}\)

min \(dp[s][u]\),u=1~n

答案就是\(dp[3^n-1][i]\)的最小值

BZOJ3717 Pakowanie

给出n个物品和m个包,物品有各自的体积,包有各自的容量。
问将所有物品装入包中需要至少几个包。
◦ n<=24, m<=100。

贪心来看显然要用尽量用最大的那几个, 所以先把包从大到小排序。

设f[S]为把集合S放入包后至少要用到第几个包 ,g[S]记录此时用到的最后一个包能剩余的最大体积。

转移时枚举接下来放哪个物品即可。
时间复杂度O(n*2^n)

只是口胡rwr,你让我写代码我一个都写不出来

状态压缩dp相关的更多相关文章

  1. [转]状态压缩dp(状压dp)

    状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的 ...

  2. 状态压缩DP总结

    POJ1185 炮兵部队问题: 在平原上才能放置炮兵,每个炮兵的上下左右2格之内都不能出现别的炮兵 可以考虑在当前行放置炮兵它的右侧和下侧绝对不会出现炮兵即可,左侧和上侧就能省去考虑 明显的状态压缩d ...

  3. 浅谈状态压缩DP

    浅谈状态压缩DP 本篇随笔简单讲解一下信息学奥林匹克竞赛中的状态压缩动态规划相关知识点.在算法竞赛中,状压\(DP\)是非常常见的动规类型.不仅如此,不仅是状压\(DP\),状压还是很多其他题目的处理 ...

  4. hoj2662 状态压缩dp

    Pieces Assignment My Tags   (Edit)   Source : zhouguyue   Time limit : 1 sec   Memory limit : 64 M S ...

  5. POJ 3254 Corn Fields(状态压缩DP)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4739   Accepted: 2506 Descr ...

  6. [知识点]状态压缩DP

    // 此博文为迁移而来,写于2015年7月15日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w6jf.html 1.前 ...

  7. HDU-4529 郑厂长系列故事——N骑士问题 状态压缩DP

    题意:给定一个合法的八皇后棋盘,现在给定1-10个骑士,问这些骑士不能够相互攻击的拜访方式有多少种. 分析:一开始想着搜索写,发现该题和八皇后不同,八皇后每一行只能够摆放一个棋子,因此搜索收敛的很快, ...

  8. DP大作战—状态压缩dp

    题目描述 阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了.现在,零崎要在地图上 ...

  9. 状态压缩dp问题

    问题:Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Ev ...

随机推荐

  1. cocos2d 15款游戏源码

    https://blog.csdn.net/jailman/article/details/78678972

  2. 苹果cms开启防红跳转后,提示模板文件不存在解决方法

    1,苹果cms开启防红跳转后,提示模板文件不存在(如下图)这是因为你使用的模板里面缺少苹果cms自带的防红跳转模板导致,遇到这种状况后需要把苹果cms默认自带的( template/default_p ...

  3. mvn deploy上传私服Nexus时遇到的坑--ReasonPhrase: Forbidden.

    用maven deploy上传jar包时,遇到了ReasonPhrase: Forbidden 错误,截图如下: 折腾了好久,终于解决,现把步骤简单记录如下: 1.自建仓库eagle-sky: 2.设 ...

  4. 前台ajax传数组,后台java接收

    后端 //添加 @RequestMapping(value = "checkChoise") @ResponseBody ResultJson checkChoise(@Reque ...

  5. 2018-2019-2-20175225 实验三 《敏捷开发与XP实践》实验报告

    一.实验内容与步骤 1.安装.使用alibaba插件规范代码 - 在IDEA的setting中找到plugins并搜索alibaba,点击install进行安装 - 重启IDEA后,在代码中右击点击编 ...

  6. Using FileUpload

    Using FileUpload FileUpload can be used in a number of different ways, depending upon the requiremen ...

  7. @清晰掉 c语言三"巨头" const:volatile:static

    const: 1.如果把const放在变量类型前,说明这个变量的值是保持不变的(即为常量),改变量必须在定义时初始化,初始化后对她的任何赋值都是非法的. 2.当指针或是引用指向一个常量时,必须在类型名 ...

  8. Arthas随笔

    目录 Arthas 安装Java 安装 Arthas Arthas 命令及示例 源码分析 Arthas 安装Java 下载jdk 注意 下载的JDK版本要与linux操作系统相匹配,否则汇报No su ...

  9. Oracle JET Model 数据获取与使用

    Oracle JET 应用程序数据可以来自生成 JSON 数据的任何 Web 数据源,例如 REST 服务,服务器发送事件(SSE)或 WebSocket .此外,Oracle JET 还提供了基于 ...

  10. 使用指定MTU到特定IP

    ping指令使用指定MTU到特定IP 命令如下 45.58.185.18 这里MTU为1300