poj 1185 状压DP

如果做了上一篇博客的题,这道题就很容易推出dp方程以及写函数了

dp[i][j][k]  当前为第i行,第i行状态为k,第i-1行状态为j的时候的炮兵总数

1、注意dp[][][]初始化为-1,而不是0,这样可以标定之前有的状态不可行,不要继续推下去,否则还是会有错解的

2、初始化,dp[1][0][i]  0表示第一个合法状态就是全0的状态

开始样例不过,因为那个求二进制里面有几个1的地方弄错了,哎。。。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define IN(s) freopen(s,"r",stdin)
#define CL(a,b) memset(a,b,sizeof(a))

const int MAXN = 13*13;

ll dp[MAXN][70][70];
int all[70];
int sta[MAXN*MAXN];//每一行的状态
char mat[MAXN*MAXN][MAXN];
int bit[1<<12];
int scnt,n,m;
//schar mat[MAXN*MAXN][MAXN];

int cal(int x)
{
    int ret=0;
    while(x)
    {
        if(x&1)ret++;
         x/=2;
    }
    return ret;
}

void init()
{
    CL(bit,0);
    CL(dp,0xff);
    scnt=0;
    int tot=1<<m;
    for(int i=0;i<tot;i++)
    {
        if(i&(i<<1) || i&(i<<2) || i&(i>>1) || i&(i>>2));
        else
        {

            all[scnt]=i;
            bit[scnt]=cal(i);
            ///
            //printf("##%d bit=%d\n",i,bit[scnt]);
            //////
            scnt++;
        }
    }
}

int legal(int x, int y) //地形与兵匹配
{
    //if(x&y || x&(y<<1) || x&(y<<2) || x&(y>>1) || x&(y>>2))
    if( x&y ) return 0;
    else  return 1;
}

int main()
{
    //IN("poj1185.txt");
    char c;

    while(~scanf("%d%d",&n,&m))
    {
        getchar();
        init();
        sta[0]=0;
        for(int i=1;i<=n;i++)
        {
            sta[i]=0;
            for(int j=1;j<=m;j++)
            {
                mat[i][j]=getchar();
                if(mat[i][j] == 'H')sta[i]+=(1<<(m-j));
            }
            getchar();
        }
        int scnt2=scnt;
        /*int scnt2=0,tmp=1<<m;
        while(all[scnt2]<tmp)///////////
            scnt2++;*/
        //scnt2--;
        for(int i=0;i<scnt2;i++)
            if(legal(sta[1],all[i]))
                dp[1][0][i]=bit[i];
        //////////////////////////
       // rep(i,0,scnt2)
         //   printf("%lld ",dp[1][0][i]);
       // putchar('\n');
        ///////////////////////////
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<scnt2;j++)//i
            {
                if(!legal(sta[i],all[j]))continue;
                for(int k=0;k<scnt2;k++)//i-1
                {
                    if(!legal(sta[i-1],all[k]))continue;
                    if( all[j]&all[k] )continue;    //列判断
                    for(int p=0;p<scnt2;p++)//i-2
                    {
                        if(!legal(sta[i-2],all[p]))continue;
                        if( all[j]&all[p] || all[k]&all[p] )continue;   //列判断
                        if(dp[i-1][p][k] == -1)continue;//不可行
                        dp[i][k][j]=max(dp[i-1][p][k]+bit[j],dp[i][k][j]);
                    }
                }
            }
        }
        ll ans=0;
        for(int i=0;i<scnt2;i++)
            for(int j=0;j<scnt2;j++)
                ans=max(ans,dp[n][j][i]);
        printf("%lld\n",ans);
    }
    return 0;
}


你可能感兴趣的:(poj 1185 状压DP)