状态压缩dp学习

状态压缩dp学习

以 P1879 为例

#include <bits/stdc++.h>
using namespace std;
const int M = 1e9;
int m, n, f[13][4096], F[13], field[13][13];
// max state: (11111111111)2 = (4095)10
bool state[4096];
int main()
{ 
	//状态压缩dp学习(代码非原创,注释都是自己写的,看了好多篇博客,感觉状压dp看代码比较好理解)
	//状压dp,本质上是一种暴力枚举,没有优化时空复杂度,而是利用位运算,方便了代码的书写(不然要写好多循环和判断)
	// 既然是二进制位运算,又没有优化复杂度,那么它通常用于取/不取(0/1)且问题规模很小的问题,比较好识别(大概)
	//01背包也可以状态压缩 
	//部分位运算 
	// a & b 存在同时为1的情况,不为0; 用于判断上下相邻。 
	// j & f==j 时 j的1包含于f的1; 用于和题目自身状态进行比较 
	// a & 1 取最后一位 
	// <<左移 乘2;
	// >>右移 除以2 并舍去取整 
	// 左移 右移可用于判断状态合法性(左右相邻)。 
    cin >> m >> n;
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
            cin >> field[i][j];//原始场地 
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
            F[i] = (F[i] << 1) + field[i][j];//场地转换为状态 
    // F[i]: state on line i
    int MAXSTATE = 1 << n;
    for (int i = 0; i < MAXSTATE; i++)
        state[i] = ((i&(i<<1))==0) && ((i&(i>>1))==0);//判断当前状态是否合法(左右不相邻) 
    f[0][0] = 1;
    for (int i = 1; i <= m; i++)
        for (int j = 0; j < MAXSTATE; j++)
            if (state[j] && ((j & F[i]) == j))//状态合法(左右合法 并且 符合原场地要求) 
                for (int k = 0; k < MAXSTATE; k++)
                    if ((k & j) == 0)//上下状态不相邻 (上下合法)  
                        f[i][j] = (f[i][j] + f[i-1][k]) % M;
    int ans = 0;
    for (int i = 0; i < MAXSTATE; i++)
        ans += f[m][i], ans %= M;
    cout << ans << endl;
    return 0;
}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值