void-man

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

很久就看推荐题目有这个了,一直没做,因为看了好几次没看懂,都说dp,这几天看了状态压缩后明白了,其实就是用二进制来表示各个位置的状态

然后进行枚举,把状态放进数组里就行,在这里用dp[i][j][k]表示第i行,当前j状态,i-1行是k状态时候的最大炮数

dp[i][j][k]=MAX(dp[i][j][k],dp[i-1][k][p]+sum[j])

#include <stdio.h>
#include <string.h>
#include <iostream>
#define MAX(a,b) (a)>(b)?(a):(b)
using namespace std;
int dp[105][65][65],ant[105],n,m,k,map[105],sum[105];
bool ok(int x)
{
    if(x&(x<<1))return false;//判断一行中,是否有两个1间隔小于2
    if(x&(x<<2))return false;
    return true;//没有的话是一个合法的状态
}
int getsum(int x)//此种状态下有多少个1
{
    int num=0;
    while(x>0)
    {
        if(x&1)num++;
        x>>=1;
    }
    return num;
}
void find()
{
    memset(ant,0,sizeof(ant));
    for(int i=0;i<(1<<m);i++)
    {
        if(ok(i))
        {
        ant[k]=i;
        sum[k++]=getsum(i);
        }

    }
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(dp,-1,sizeof(dp));
        for(int i=0;i<n;i++)
         {
             for(int j=0;j<m;j++)
         {
             char tmp;
            cin>>tmp;
             if(tmp=='H')map[i]=map[i]|(1<<j);//把第i行原始状态取反后放入map[i]
         }

         }
         k=0;
         find();
         for(int i=0;i<k;i++)//初始化第一行状态,特殊考虑
         if(!(ant[i]&map[0]))
         dp[0][i][0]=sum[i];
         for(int r=1;r<n;r++)
         {
             for(int i=0;i<k;i++)//第r行的状态
             {
                 if(map[r]&ant[i])continue;
                 for(int p=0;p<k;p++)//枚举第r-1行状态
                 {
                     if(ant[p]&ant[i])continue;//r与r-1没有想接触的
                     for(int q=0;q<k;q++)//枚举第r-2行
                     {
                          if(ant[i]&ant[q])continue;//r与r-2行没有接触的
                          if(dp[r-1][p][q]==-1)continue;
                          dp[r][i][p]=MAX(dp[r][i][p],dp[r-1][p][q]+sum[i]);
                     }

                 }
             }
         }
         int ans=0;
         for(int i=0;i<k;i++)
          for(int j=0;j<k;j++)
         ans=MAX(ans,dp[n-1][i][j]);
         printf("%d\n",ans);
    }
}

posted on 2011-06-04 14:52  void-man  阅读(236)  评论(0)    收藏  举报