• hdu 1185 状压dp 好题 (当前状态与上两行有关系)


    /*
    状压dp
    刚开始&写成&&看了好长时间T0T.
    状态转移方程
     dp[i][k][j]=Max(dp[i][k][j],dp[i-1][l][k]+num[i][j]);(第i行的第j个状态有上一行的第k个状态得到)
     num[i][j]有两个功能,第一:判断第i行第j个状态是否合法
                          第二:判断第i行第j个状态的数目
    */
    #include<stdio.h>
    #include<string.h>
    #define N 110
    int dp[N][N][N];
    char s[N][N];
    int len;
    int ss[N],ans,num[N][N];
    int n,m;
    int lower[20];
    int f(int i,int d)
    {
        int k=0,j;
        for(j=0; j<m; j++)
        {
            if(lower[j]&d&&s[i][j+1]=='H')return -1;
            if(lower[j]&d&&s[i][j+1]=='P')k++;
        }
        return k;
    }
    int Max(int v,int vv)
    {
        return v>vv?v:vv;
    }
    void slove()
    {
        int i,j,k,l;
        memset(dp,-1,sizeof(dp));
        len=0;
        for(i=0; i<(1<<m); i++)
        {
            if(((i<<1)&i)||((i<<2)&i))continue;
            ss[len++]=i;
        }
        memset(num,-1,sizeof(num));
        for(i=1; i<=n; i++)
            for(j=0; j<len; j++)
            {
                k=f(i,ss[j]);
                if(k!=-1)
                    num[i][j]=k;
                //printf("%d %d %d
    ",i,j,num[i][j]);
            }
        for(i=0; i<len; i++)//初始化第一行
        {
            num[0][i]=0;
            if(num[1][i]==-1)continue;
            dp[1][0][i]=num[1][i];//因为0的是否没有下面ss[j]&ss[l]的限制
            if(ans<dp[1][0][i])
                ans=dp[1][0][i];
        }
        for(i=2; i<=n; i++)
            for(j=0; j<len; j++)
            {
                if(num[i][j]==-1)continue;
                for(k=0; k<len; k++)
                {
                    if(num[i-1][k]==-1)continue;
                    for(l=0; l<len; l++)
                    {
                        if(num[i-2][l]==-1)continue;
                        if(ss[j]&ss[k])continue;
                        if(ss[j]&ss[l])continue;
                        if(dp[i-1][l][k]==-1)continue;
                        dp[i][k][j]=Max(dp[i][k][j],dp[i-1][l][k]+num[i][j]);
                     //   printf("%d %d %d %d %d %d
    ",i,num[i][j],dp[i][k][j],dp[i-1][l][k],ss[j],ss[k]);
                        if(ans<dp[i][k][j])
                            ans=dp[i][k][j];
                    }
                }
            }
        return ;
    }
    int main()
    {
        int i;
        lower[0]=1;
        for(i=1; i<=12; i++)
            lower[i]=lower[i-1]*2;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(i=1; i<=n; i++)
                scanf("%s",s[i]+1);
            ans=-1;
            slove();
            printf("%d
    ",ans);
        }
        return 0;
    }
    

  • 相关阅读:
    hdu--1018--Big Number(斯特林公式)
    NYOJ--56--阶乘因式分解(一)
    hdu--1711--kmp应用在整形数组--Number Sequence
    HDU--1358--KMP算法失配函数getfail()的理解--Period
    C++STL(vector,map,set,list,bitset,deque)成员函数整理
    NYOJ--95--multiset--众数问题
    NYOJ--86--set.find()--找球号(一)
    NYOJ--19--next_permutation()--擅长排列的小明
    NYOJ--714--Card Trick
    NYOJ--2--括号配对问题
  • 原文地址:https://www.cnblogs.com/thefirstfeeling/p/4410594.html
Copyright © 2020-2023  润新知