您的位置:首页 > 其它

状态压缩DP (poj 3254, poj 1185, nyoj 81)

2014-11-30 16:19 162 查看
状态压缩DP, 一上来就卡了我好久。。。。。

poj3254应该是状态压缩里最经典(简单)得了吧


大意:就是在一块地图里种草, 左右不能相邻,上下也不能相邻, 问一共有多少种种法(什么不种也算一种)。

分析:M(<=12)行N(<=12)列的农场。很明显的的压缩DP,可以将其用二进制记录,以十进制的形式存在数组里。每一行最多12列(12个位置)所以int型足够用了。

d[i][j] = d[i][j] + d[i-1][k] (0 <= k <= N)

dp[i][j]代表第i行的第j中状态一个出现的方案个数,对于j的状态,要判断是否可以存在,并且是否有两个草地相邻(即代码中can()函数),并且还要判断j状态是否和第i-1行的的k状态的草地相邻,如果相邻的话就舍弃!

见代码吧!



可能上面那个是最简单的压缩DP了,做完这个我紧接着做了nyoj81,各种超内存啊!!

nyoj81 (和poj1185几乎一样)

描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:



如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。

现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
输入第一行输出数据测试组数X(0<X<100)

接下来每组测试数据的第一行包含两个由空格分割开的正整数,分别表示N和M; 接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。0<=N <= 100;0<=M <= 10。输出每组测试数据输出仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。

样例输入
1
5 4
PHPP
PPHH
PPPP
PHPP
PHHP

样例输出
6

分析:首先这回求得是:最多能摆放的炮兵部队的数量, 不再求总的方法个数了。1.地图转换成一个二进制的数组(a[]),即一个整数表示一行的地形(1表示高地,0表示平原)。

2.方程先上吧: d[i][j][k] = max(d[i][j][k], d[i-1][k][z] + number(row[j])); d[i][j][k]表示前i行, 第i行状态为j, i-1 行状态为k时的最多摆放数。row[j]是i行的某种状态,number(x)功能:返回x用二进制表示时1的个数。

3.应为攻击范围沿横向左右各两格,沿纵向上下各两格,所以再求每一行时应该前两行的状态都考虑。 相邻三行不能冲突。首先,对行的遍历,然后对当前行的状态遍历,然后对上一行的状态遍历,再对上上行的状态遍历,这个方程就是遍历上一行状态为k和上上行状态为z时的部署数量,求出最大部署数,再加上本行即i行,j状态的部署(number(row[j]))。

4.当时一看0<=M<=10,觉得很明朗啊,。。。可是一个三维数组d[100][2^10][2^10]太大了,各种超啊。。。看了大神的分析,才恍然大悟。。。。。从题中可分析每行中每两个部署位置中间至少个两个位置,所以我们可以预先判断一下哪些情况才是满足的。其实满足的情况只有60种,我们可以将这些满足的状态预先处理好存在row[]数组中。这样三维数组就可以变成d[100][60][60]。这就不超了!!

代码:



额。。。。我这表达可能有点。。。。谢谢!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: