状压DP(奇怪的东西)

 简介

 状态压缩动态规划(简称状压DP)是很是典型的一类DP。他是利用二进制来描述状态的一种DP方式,你们都知道,DP是解决多阶段决策最优化问题的思想方法,可是有时候阶段多了,维度多了,数组也就爆了,由于虽然维度多,可是有些空间可能用不到,这就很浪费了,(主要是维度多了处理麻烦很恶心)因此咱们就把咱们就把一组数据压到一个int变量里面(只要是整形,什么都好啦)数组

  举个生动形象的例子,在01背包中,n个物品的选择方式,就能够用二进制数来表示:1 0 1 1 0(n=5),从低位开始,表示1不选,2选,3选,4不选,5选。优化

  既然它与二进制有关,因此咱们就须要讲一讲二进制啦spa

位运算

基本运算

名称code

做用blog

举例get

左移(<<) 位左移运算将整个数按位左移若干位,左移后空出的部分0。 5(101)<<2=20(10100) 
右移(>>) 位右移运算将整个数按位右移若干位,右移后空出的部分填0。 5(101)>>2=1(1) 
按位与(&) 会将两个十进制数在二进制下进行与运算,而后返回其十进制下的值。在某一位上,只有两个数都是1才返回1 5(101)&2(10)=0 
按位或(|) 会将两个十进制数在二进制下进行或运算,而后返回其十进制下的值。在某一位上,只要有一个数是1就返回1 5(101)|2(10)=7(111) 
按位异或(^) 会将两个十进制数在二进制下进行异或运算,而后返回其十进制下的值。在某一位上,只有两个数相同才返回1 5(101)^2(10)=0 
按位非(~) 把0变成1,1变成0,而后返回其十进制下的值。 咳咳,最好不要轻易用,由于int有32位(二进制),前面的所有会变成1 

进阶运算

 

检查第i位是不是 1it

if(1<<(i-1)&x)...

检查第i位是不是 0io

if(1<<(i-1)&x==0)...

统计x中有多少个 1table

while(x) { cnt += x&1; x >>= 1; }

检查x中是否有相邻的 1ast

if(x&(x<<1))...

计算x最低位1表明的值

int lowbit(int x) { return x&(-x); }

把第i位变成 1

x |= (1<<(i-1))

把第i位变成 0

x &= ~(1<<(i-1))

把第i位取反

x ^= (1<<(i-1)

末i位取反

x^(1<<(i-1))

x包含y

if(x&y==y)...    OR if(x|y==x)...

取右边连续的1

(x^(x+1))>>1

把右边连续的0变成1

x&(x-1)

把右边连续的1变成0

x|(x+1)

把右边第一个0变成1

x|(x+1)

例题 P1879 [USACO06NOV]玉米田Corn Fields

  这是一道典型的状压DP(废话,学的状压不给状压给什么)

  咱们用一个M数组来存储每一行的状况(土地是否贫瘠),而后用state数组表示某一种种植方法是否能够知足任意两个种植物不相邻,(bool数组)。

  而后开始一行一行的枚举状态,若是可用而且没有贫瘠土地,就枚举上一排的,看不相邻的状况就转移,最后把最后一行全部的状况累计起来便可。

code

 

例题 P1896 [SCOI2005]互不侵犯

  仍是和玉米田差很少的操做,可是dp数组须要加一维,因此就成了在某一行的某种状态中已经放了x个国王有几种方法,剩下的就和上一个例题差很少了

code

相关文章
相关标签/搜索