链接:http://poj.org/problem?id=1185
题意:题目中文
这是个状态压缩dp的题,先根据行的长度m遍历保存所有可能的布置炮兵的方案,同时记录该方案炮兵的数量。
因为竖着也不能让炮兵互相攻击到,而且如果从上往下遍历的话,第i行会和i-1行和i-2行都有制约关系,我第一次和第二次想的办法都陷到这个错误了,自己水平经验都不够,没办法提早发现在后效性上犯的错误,这样没办法遍历完所有可行的方案。如果你的方案中第i-1行和i-2行是和第i行分开判断,并且没办法确定第i-1行的上一行的状态,那么十有八九就犯了和我一样的错误。
所以就需要在dp的时候必须知道滴i-1行当前状态的上一行曾选择的状态,也就是说第i行和i-1行的状态同时保存,这样才能在下一行中运用
dp[ i ][ j ][ k ] :第i行的状态为j,上一行的状态为k,并保存最大炮兵数
设总共可能的状态为up个
状态转移方程为:
在第i行选择j状态保证和i-1行,i-2行状态的合法的前提下有
dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][0~up]+sum[j]),k=0~up
代码:
#include
#include
#define max(a,b) (a)>(b)?(a):(b)
int mp[105],dp[105][65][65];//dp[i][j][k],第i行状态是j,上一行的状态是k
int sum[65],sta[65];
int up;
int is_ok(int x)
{
if(x&(x<<1))
return 0;
if(x&(x<<2))
return 0;
return 1;
}
int getsum(int x)
{
int sum=0;
while(x>0)
{
if(x&1)
sum++;
x>>=1;
}
return sum;
}
void ini(int m)
{
int i;
up=0;
for(i=0;i<(1<=2)
for(i=0;idp[1][i][k]))
dp[1][i][k]=dp[0][k][0]+sum[i];
for(i=2;idp[i][j][k])
dp[i][j][k]=dp[i-1][k][l]+sum[j];
int ans=0;
for(i=0;ians)
ans=dp[n-1][i][j];
printf("%d\n",ans);
}
return 0;
}