zoukankan      html  css  js  c++  java
  • 0x56 状压DP

    gan这两题怎么差不多

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    
    bool u[5100];
    LL f[20][5100];
    int main()
    {
        
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            if(n==0&&m==0)break;
            int li=(1<<m)-1;
            
            for(int i=0;i<=li;i++)
            {
                int cc=0;u[i]=true;
                for(int j=m-1;j>=0;j--)
                    if(i&(1<<j))
                    {
                        if(cc%2==1)u[i]=false;
                        cc=0;
                    }
                    else cc++;
                if(cc%2==1)u[i]=false;
            }
            
            //--------------------------
            
            memset(f,0,sizeof(f));f[0][0]=1;
            for(int i=1;i<=n;i++)
                for(int zt=0;zt<=li;zt++)
                    for(int lzt=0;lzt<=li;lzt++)
                        if((lzt&zt)==0&&u[lzt|zt]==true)
                            f[i][zt]+=f[i-1][lzt];
            printf("%lld
    ",f[n][0]);
        }
        return 0;
    }
    poj2311
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    
    char ss[110][20]; int b[110];
    int f[2][2100][2100];
    int len,z[2100],d[2100];
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%s",ss[i]+1);
        for(int i=1;i<=n;i++)
        {
            b[i]=0;
            for(int j=1;j<=m;j++)
                if(ss[i][j]=='H')b[i]^=(1<<(j-1));
        }
        
        int li=(1<<m)-1;len=0;
        for(int i=0;i<=li;i++)
        {
            int cc=-3,dd=0;bool bk=true;
            for(int j=0;j<=m-1;j++)
                if(i&(1<<j))
                {
                    if(j-cc<=2){bk=false;break;}
                    cc=j;dd++;
                }
            if(bk==true){z[++len]=i;d[len]=dd;}
        }
        
        //--------------------------
        
        int now=0,ans=0;f[now][0][0]=1;
        for(int i=1;i<=n;i++)
        {
            now^=1;
            for(int j=1;j<=len;j++) if(i==1||(!(z[j]&b[i-1])))
            {
                for(int k=1;k<=len;k++) if( (!(z[k]&b[i])) && (!(z[j]&z[k])) )
                {
                    f[now][j][k]=0;
                    for(int p=1;p<=len;p++) if( (i<=2||(!(z[p]&b[i-2]))) && (!(z[j]&z[p])) && (!(z[k]&z[p])) )
                    {
                        f[now][j][k]=max(f[now][j][k],f[now^1][p][j]+d[k]);
                    }
                    ans=max(ans,f[now][j][k]);
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    poj1185

    同样0/1区分特殊位置,同样预处理当前行的合法状态,同样用位运算判断合法

    还是插头DP有意思哈哈,还很快哩

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=10007;
    
    struct Plug_DP
    {
        LL f[5100];
        int top;LL sta[5100],hash[5100];
        void pha(LL s,LL sum)
        {
            LL x=s%mod; 
            while(hash[x]!=0&&sta[hash[x]]!=s)x=(x+1)%mod; 
            if(hash[x]==0)sta[++top]=s,hash[x]=top;
            f[hash[x]]+=sum;
        }
        void clean()
        {
            top=0;
            memset(hash,0,sizeof(hash));
            memset(f,0,sizeof(f));
        }
    }dp[2];
    LL get_bracket(LL s,LL p)
    {
        return ((s>>(p-1))&1);
    }
    LL set_bracket(LL s,LL p,LL v)
    {
        s^=(get_bracket(s,p)<<(p-1));
        s^=(v<<(p-1));
        return s;
    }
    
    int n,m;LL ans;
    void Plug_DP()
    {
        int pre=0,now=1;
        dp[now].clean();dp[now].pha(0,1);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                swap(pre,now);dp[now].clean();
                for(int k=1;k<=dp[pre].top;k++)
                {
                    LL s=dp[pre].sta[k],sum=dp[pre].f[k];
                    LL p=get_bracket(s,j),q=get_bracket(s,j+1);
                    
                    if(i==n&&j==m)
                    {
                        if((p==1&&q==0)||(p==0&&q==1))ans+=sum;
                        continue;
                    }
                    
                    if(p==0&&q==0)
                    {
                        if(i!=n)
                        {
                            s=set_bracket(s,j,1);
                            s=set_bracket(s,j+1,0);
                            dp[now].pha(s,sum);
                        }
                        if(j!=m)
                        {
                            s=set_bracket(s,j,0);
                            s=set_bracket(s,j+1,1);
                            dp[now].pha(s,sum);
                        }
                    }
                    if((p==1&&q==0)||(p==0&&q==1))
                    {
                        s=set_bracket(s,j,0);
                        s=set_bracket(s,j+1,0);
                        dp[now].pha(s,sum);
                    }
                }
            }
            for(int k=1;k<=dp[now].top;k++)dp[now].sta[k]<<=1;
        }
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            if(n==0&&m==0)break;
            ans=0;Plug_DP();
            printf("%lld
    ",ans);
        }
        return 0;
    }
    poj2311(Plug_DP)
  • 相关阅读:
    POJ 1142 Smith Numbers
    POJ 1171 Letter Game 解题思路
    人人德克萨斯牌出手规则整理
    OpenMP相关知识索引
    如何进行有效的沟通
    台哥算法练习:一个for循环打印九九乘法表
    啊哈,381654729!
    发牌的小窍门
    判断数abcdef能否被k整除(k属于[2,9])
    如何在数轴上找到一个数的倒数
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9459943.html
Copyright © 2011-2022 走看看