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)
原文地址:https://www.cnblogs.com/AKCqhzdy/p/9459943.html