poj 1185 炮兵阵地(状压dp)

来源:互联网 发布:杰科网络电视机顶盒r1 编辑:程序博客网 时间:2024/04/30 13:08

题目链接:

http://poj.org/problem?id=1185

题目大意:

中文题。

范围:

N <= 100;M <= 10。

思路:

状压dp。

还是将炮兵摆放的地方设1,不放的地方设0。

因为他对炮兵的攻击范围做了要求,也就是相邻的炮兵位置不能小于2。那么我们就要先筛选出满足这个硬性条件的状态。

然后我们可以发现,对于第i行的状态,与上一行以及上上一行有关。

所以考虑设一个三维dp[i][j][k],代表到第i行时,第i行的状态为j,第i-1行的状态为k时候的最大的可以摆放的数量。

这样我们就可以得到转移方程:dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]),这里num[j]表示在第i行的状态j里面放了多少个炮兵,也就有多少个1。

代码:

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;int n,m,kk;int dp[105][110][110],cur[105],state[110],num[110];bool ok(int x){    if(x&(x<<1))return 0;    if(x&(x<<2))return 0;    return 1;}void init(){    for(int i=0;i<(1<<m);i++)    {        if(ok(i)){state[kk++]=i;        }    }}int cal(int x)   //计算x的状态下有多少个1;{    int ans=0;    while(x)    {        ans++;        x&=(x-1);    }    return ans;}bool judge(int x,int y){    return x&y;}int main(){    char c;    int i,j,k,l;    while(~scanf("%d%d",&n,&m))    {        kk=0;        memset(num,0,sizeof(num));        memset(dp,0,sizeof(dp));        memset(cur,0,sizeof(cur));        for(i=1;i<=n;i++)            for(j=1;j<=m;j++)        {            cin>>c;            if(c=='H')cur[i]+=(1<<(m-j));        }        init();        for(i=0;i<kk;i++)        {            num[i]=cal(state[i]);            if(!judge(cur[1],state[i]))                {dp[1][i][0]=num[i];    //边界处理        }        }        for(i=2;i<=n;i++)        {            for(j=0;j<kk;j++)            {                if(judge(cur[i],state[j]))continue;                for(k=0;k<kk;k++)                {                    if(judge(state[j],state[k]))continue;                    for(l=0;l<kk;l++)                    {                        if(judge(state[k],state[l]))continue;                        if(judge(state[j],state[l]))continue;                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]);                    }                }            }        }        int ans=0;            for(j=0;j<kk;j++)            for(k=0;k<kk;k++)            ans=max(ans,dp[n][j][k]);            printf("%d\n",ans);    }}


0 0