炮兵阵地--POJ 1185

1、题目类型:DP。

2、解题思路:(1)确定N列的情况下同行不产生冲动的n中可能(因为N<=10,所以n<=60);(2)从上向下逐行,从左往右逐列遍历,其中dp[i][j][k]表示第 i 行时候,j 表示 i 行的状态情况,k 表示 i-1 行的状态情况下,最大可能的炮兵安置数目;(3)结果为最后一行所有情况的最大值。

3、注意事项:注意1<<N表示2^N;获取N列n种情况时的位运算处理。

4、实现方法:

#include<iostream>
using namespace std;

int status[105],judge[66];
int num[66];
int dp[105][66][66];
int M,N,cnt;

inline
int max(int p1,int p2)
{
return p1>p2?p1:p2;
}

void Init()
{
int i,t,nn;
for(i=0;i<(1<<N);i++)
{
nn
=0;
if( ((i<<1)&i)||((i<<2)&i))//不合法
continue;
judge[cnt]
=i;
t
=i;
while(t)
{
if(t&1)
nn
++;
t
=(t>>1);
}
num[cnt
++]=nn;
}
}

void DP()
{
int i,j,k,ans;
for(i=0;i<M;i++)
{
for(j=0;j<cnt;j++)
{
if((status[i] & judge[j])!=judge[j])
continue;
if(i==0)
{
dp[i][j][
0]=num[j];
continue;
}
if(i==1)
{
for(k=0;k<cnt;k++)
{
if(judge[j] & judge[k])
continue;
dp[i][j][k]
=max(dp[i][j][k],dp[i-1][k][0]+num[j]);
}
continue;
}
for(k=0;k<cnt;k++)
{
if(judge[j] & judge[k])
continue;
for(int p=0;p<cnt;p++)
{
if(judge[k] & judge[p])
continue;
if( (judge[j] & judge[k]) || (judge[j] & judge[p]))
continue;
dp[i][j][k]
=max(dp[i][j][k],dp[i-1][k][p]+num[j]);
}
}
}
}
ans
=0;
for(i=0;i<cnt;i++)
for(j=0;j<cnt;j++)
if(dp[M-1][i][j]>ans)
ans
=dp[M-1][i][j];
cout
<<ans<<endl;
}

int main()
{
int i,j,tmp;
char ch;
scanf(
"%d%d",&M,&N);
for(i=0;i<M;i++)
{
getchar();
tmp
=0;
for(j=N-1;j>=0;j--)
{
scanf(
"%c",&ch);
if(ch=='P')
tmp
+=(1<<j);
}
status[i]
=tmp;
}
Init();
DP();
return 0;
}

 

posted @ 2010-10-03 10:28  勇泽  阅读(284)  评论(0编辑  收藏  举报