状压DP入门——Bzoj1725 牧场的安排题解

状压DP入门——Bzoj1725 牧场的安排

状压DP是DP中不太好理解的一种算法,其关键点就在于将每个状态转化为二进制再储存为十进制储存(如:True,False,True,False四个状态转为二进制数1010再转为十进制数10储存),其优点是可以在较小的内存占用中表示较多的状态(long long int大约可压缩64种状态),同时运用位运算可以得到数组访问处理所达不到的速度,所以状压DP非常重要。

话不多说,先上例题

【题目描述】
原题来自:USACO 2006 Nov. Gold
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行:输出一个整数,即牧场分配总方案数除以 108 的余数。
【输入样例】
2 3
1 1 1
0 1 0
【输出样例】
9

先考虑记录方案方法

对于每块地只有两种情况,放牛和不放牛,所以可以用二进制储存状态进行压缩。
先看个例子:

放牛 不放牛 放牛
不放牛 放牛 不放牛
放牛 不放牛 放牛

将放牛状态记录为1,不放牛记录为0,那么记录下的状态为:

1 0 1
0 1 0
1 0 1

这里不难理解,然后是压缩状态。我们逐行进行压缩,那么第一行包含的状态1,0,1转为十进制数记录,即5;第二行包含的状态0,1,0也转为十进制压缩储存,即2;同理,对第三行包含的状态进行压缩,得到5。再将压缩得到的数据5,2,5汇总为数组,就可以得到数组:

5
2
5

即每一行的一个数包含了该行的三个状态,也就是状态压缩,最后转为大家熟悉的横向的数组,得到:

5 2 5

这样就可以表示放牛的状态了。取用和操作状态时用位运算符直接对他们的二进制进行操作即可。
位运算的定义及运算规则可见下面两个表格:

类 型 运算符 含义 规则
位逻辑运算符 & 按位与 同位同为1该位为1,否则为0
位逻辑运算符 | 按位或 同位中有一个为1该位为1,否则为0
位逻辑运算符 ^ 按位异或 同位相同为1,否则为0
位逻辑运算符 ~ 取反 0变1,1变0
移位运算符 << 左移 整体左移,右边末尾添0,左溢出截断
移位运算符 >> 右移 整体右移,左边末尾添0,右溢出截断

再考虑每行的所有情况(暂不考虑土地的影响及竖向限制)

因为我们是横向压缩状态,所以我们只考虑横向的所有情况。因为每行的列数相同,所以所有可能的情况是相同的! 我们仅需枚举一次每行中所有不冲突的情况即可套用到所有行。情况的穷举首先会想到dfs,那就先用dfs穷举。
Code:

int list[4099];//用于记录所有已枚举的情况,大小为1<<12
int item = 0;//记录情况总数
int range = 0;//设置枚举情况的长度
void dfs(int deep, int last)
{
   
	if (deep >= range)//判断枚举位数是否达到长度
	{
   
		list[item++] = last;//记录当前情况
		return;
	}
	dfs(deep + 1, last << 1);//无条件左移
	if (!(last & 1))//判断最后一位是否为1,因为1的二进制为0001
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值