输入样例:
1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0
输出样例:
1 0 1 2 3 5 144 51205
#include#include #include #include using namespace std; typedef long long LL; const int N = 12, M = 1<<12; vector > state(M); bool st[M]; int m,n; LL f[N][M]; //第一维表示"列", 第二维表示对应的状态(以二进制表示) int main() { while((cin>>n>>m) && (m|n)) { //第一次预处理,判断每一种状态留下的连续的空缺数是否都为偶数 //看第i-2列伸出来的和第i-1列伸出去的是否冲突 //对状态数组进行初始化,为之后进一步的处理做铺垫 for(int i = 0; i < 1< >j & 1){//★ if(cnt & 1){ isEven = false; break; } }else{ cnt ++; } } if(cnt & 1) isEven = false; st[i] = isEven; } //第二次预处理 //判断第i-2列伸出来的和第i-1列伸出去的是否冲突 for(int j = 0; j < 1<
感受:在第三步正式进行状态压缩之前, 我们努力的方向如下,
★筛除符合以下几种情况的状态(满足任一条即可)
- ①对本列状态进行自我批判(纵向空白能否被2✖1的块填充[计数,判断奇偶])
- ②相邻的列与列之间(其实就是把2^n个状态相互比较)凹凸不匹配,以及两个状态合并后自我批判是否合理(用到 或运算 和 ①中筛出来的st[]数组)


![[★状态压缩DP★] AcWing 291. 蒙德里安的梦想 [★状态压缩DP★] AcWing 291. 蒙德里安的梦想](http://www.mshxw.com/aiimages/31/290890.png)
