炮兵阵地--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;
}