hdu4539郑厂长系列故事——排兵布阵 dp+状态压缩

/*

这题和poj的1185很像

http://blog.csdn.net/cq_pf/article/details/41931061

dp[i][j][k]  第i行在第i-1行的状态j,第i行的状态为k时的最大值
状态转移方程dp[i][j][k]=max(dp[i-1][s][j]+count(k))
count(k)为二进制状态为k时的取值
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 110
#define maxs 200
#define maxm 20
int dp[maxn][maxs][maxs];
int landstatus[maxn];//每一行的状态
int useful[maxs];//有用的状态
int n,m;
int count(int x)
{
    int ans=0;
    while(x)
    {
        if(x%2)
        ans++;
        x/=2;
    }
    return ans;
}
int init()
{
    int upper=1<<m;
    int i,k=0;
    for(i=0;i<upper;i++)
    {
        if((i&(i<<2)))//与poj1185相比在判断有用的状态时只需要判断移两位的情况
        continue;
        useful[k++]=i;
    }
    return k;
}
int main()
{
    int i,j,k;int s;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(landstatus,0,sizeof(landstatus));
        memset(dp,-1,sizeof(dp));
        for(i=0;i<n;i++)
        {
            int temp;
            for(j=0;j<m;j++)
            {
                scanf("%d",&temp);
                if(!temp)
                landstatus[i]+=(1<<j);
            }
        }
        int topper=init();
        for(j=0;j<topper;j++)
        {
            if(useful[j]&landstatus[0])
            continue;
            dp[0][0][j]=count(useful[j]);
        }
        for(i=1;i<n;i++)
          for(k=0;k<topper;k++)
          {
              if(useful[k]&landstatus[i])
              continue;
              for(j=0;j<topper;j++)
              {
                  if((useful[j]&(useful[k]<<1))||(useful[j]&(useful[k]>>1)))//与poj之间
                  continue;                                                 //相比判断前一行和
                  for(s=0;s<topper;s++)                                     //和该行的状态只需判断
                  {                                                         //左移一位和右移一位
                      if(useful[k]&useful[s])                               //的状态
                      continue;
                      if(dp[i-1][s][j]==-1)
                      continue;
                      dp[i][j][k]=max(dp[i-1][s][j]+count(useful[k]),dp[i][j][k]);
                  }
              }
          }
          int ans=0;
          for(j=0;j<topper;j++)
          for(k=0;k<topper;k++)
          ans=max(ans,dp[n-1][j][k]);
          printf("%d\n",ans);
    }
    return 0;
}



你可能感兴趣的:(hdu4539郑厂长系列故事——排兵布阵 dp+状态压缩)