您的位置:首页 > 其它

POJ 1185 炮兵阵地 (状压DP)

2014-08-26 16:14 405 查看
题目链接

题意 : 中文题不详述。

思路 :状压DP,1表示该位置放炮弹,0表示不放。dp[i][j][k],代表第 i 行的状态为k时第i-1行的状态为 j 时放置的最大炮弹数。只是注意判断的时候不要互相攻击到就可以了,还要与地形相适应。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std ;

int dp[110][70][70] ;
int sum[150] ;
int sta[110] ;
int mapp[110] ;
char sh[110][20] ;
int num ;
int N,M ;

int getsum(int x)
{
x=(x& 0x55555555)+((x>>1)& 0x55555555);
x=(x& 0x33333333)+((x>>2)& 0x33333333);
x=(x& 0x0F0F0F0F)+((x>>4)& 0x0F0F0F0F);
x=(x& 0x00FF00FF)+((x>>8)& 0x00FF00FF);
x=(x& 0x0000FFFF)+((x>>16)& 0x0000FFFF);
return x;
}
//int getsum(int x)
//{
//    int cnt = 0 ;
//    while(x)
//    {
//        cnt ++ ;
//        x &= x-1 ;
//    }
//    return cnt ;
//}
int main()
{
while(~scanf("%d %d",&N,&M) )
{
memset(dp,-1,sizeof(dp)) ;
num = 0 ;
for(int i = 1 ; i <= N ; i++)
{
scanf("%s",sh[i]) ;
for(int j = 0 ; j < M ; j++)
{
if(sh[i][j] == 'H')
mapp[i] |= (1 << j) ;//把高原的地方标记一下
}
}
for(int i = 0 ; i < (1 << M) ; i++)//枚举所有可行的状态
{
if(i & (i << 1) || i & (i >> 1) || i & (i << 2) || i & (i >> 2))
continue ;
//    cout<<i<<" ";
sum[num] = getsum(i) ;//求i状态中1的个数
sta[num++] = i ;//将该状态存到数组中
}
// cout<<endl;
for(int i = 0 ; i < num ; i++)
{
if(sta[i] & mapp[1]) continue ;
dp[1][0][i] = sum[i] ;
}
for(int i = 2 ; i <= N ; i++)
{
for(int k = 0 ;k < num ; k++)
{
if(mapp[i] & sta[k]) continue ;
for(int j = 0 ; j < num ; j++)
{
if(sta[j] & sta[k]) continue ;
for(int h = 0 ; h < num ; h++)
{
if(sta[h] & sta[k]) continue ;
if(sta[h] & sta[j]) continue ;
if(dp[i-1][h][j] != -1)
{
dp[i][j][k] = max(dp[i][j][k],dp[i-1][h][j]+sum[k]) ;
}
}
}
}
}
int ans = 0 ;
for(int j = 0 ; j < num ; j++)
{
for(int k = 0 ; k < num ; k++)
ans = max(ans,dp
[j][k]) ;
}
printf("%d\n",ans) ;
}
return 0 ;
}


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