zoukankan      html  css  js  c++  java
  • 插头DP智障操作合集

    今天一共四道插头DP【其实都差不多】,智障错误出了不下五个:D

    来,让我好好数落我自己一下

    直接写代码注释里吧

    Eat the Trees

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int t,n,m;
    int a[15][15],sit[15];
    long long f[15][15][(1<<15)+10];//忘开long long几百次 
    void clear(){
        memset(f,0,sizeof(f));
        memset(a,0,sizeof(a));
    }
    void work(int x,int y){
        int plug1=sit[y-1],plug2=sit[y];
        for(int i=0;i<sit[m+1];i++){
            if(a[x][y]){
                f[x][y][i]+=f[x][y-1][i^plug1^plug2];
                if(((i>>y-1)&1)==((i>>y)&1))continue;
                f[x][y][i]+=f[x][y-1][i];
            }
            else{
                if(!(i&plug1)&&!(i&plug2))f[x][y][i]=f[x][y-1][i];
                else f[x][y][i]=0;
            }
        }
    }
    int main()
    {
        scanf("%d",&t);
        sit[0]=1;
        for(int i=1;i<=15;i++)sit[i]=sit[i-1]<<1;
        while(t--){
            clear();
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    scanf("%d",&a[i][j]);
                }
            }
            f[1][0][0]=1;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    work(i,j);
                }
                if(i!=n){
                    for(int j=0;j<sit[m];j++){
                        f[i+1][0][j<<1]=f[i][m][j];
                    }
                }
            }
            printf("%lld
    ",f[n][m][0]);
        }
        return 0;
    }
    //第一篇几乎是对着前辈的代码打的 大概没什么问题 【虽然本质应该是背着打然后对着改】

    Ural 1519 Formula 1

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,m,e1,e2,las,now,tt;
    const int has=299989;
    int sit[15],a[2][300005],mp[15][15],head[300005],Next[300005],tot[2];
    long long f[2][300005],ans;
    char c[15];
    void ins(int zt,long long num){
        int pos=zt%has+1;
        for(int i=head[pos];i;i=Next[i]){
            if(a[now][i]==zt){
                f[now][i]+=num;
                return;
            }
        }
        Next[++tot[now]]=head[pos],head[pos]=tot[now];
        a[now][tot[now]]=zt,f[now][tot[now]]=num;
    }
    void work(){
        tot[now]=1,f[now][1]=1,a[now][1]=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=tot[now];j++)a[now][j]<<=2;
            for(int j=1;j<=m;j++){
                las=now,now^=1;
                memset(head,0,sizeof(head));
                tot[now]=0;
                for(int k=1;k<=tot[las];k++){
                    int zt=a[las][k],b1=((zt>>((j-1)*2))%4),b2=((zt>>(j*2))%4);
                    long long num=f[las][k];
                    if(!mp[i][j]){
                        if(!b1&&!b2)ins(zt,num);
                    }
                    else if(!b1&&!b2){
                        if(mp[i+1][j]&&mp[i][j+1])ins(zt+sit[j-1]+2*sit[j],num);
                    }
                    else if(b1&&!b2){
                        if(mp[i][j+1])ins(zt-sit[j-1]*b1+sit[j]*b1,num);
                        if(mp[i+1][j])ins(zt,num);
                    }
                    else if(!b1&&b2){
                        if(mp[i+1][j])ins(zt-sit[j]*b2+sit[j-1]*b2,num);
                        if(mp[i][j+1])ins(zt,num);
                    }
                    else if(b1==1&&b2==1){
                        int kl=1;
                        for(int t=j+1;t<=m;t++){
                            if((zt>>(t*2))%4==1)kl++;
                            if((zt>>(t*2))%4==2)kl--;
                            if(!kl){
                                ins(zt-sit[j-1]-sit[j]-sit[t],num);
                                break;
                            }
                        }
                    }
                    else if(b1==2&&b2==2){
                        int kl=1;
                        for(int t=j-2;t>0;t--){
                            if((zt>>(t*2))%4==1)kl--;
                            if((zt>>(t*2))%4==2)kl++;
                            if(!kl){
                                ins(zt+sit[t]-2*sit[j-1]-2*sit[j],num);
                                break;
                            }
                        }
                    }
                    else if(b1==2&&b2==1){
                        ins(zt-2*sit[j-1]-sit[j],num);
                    }
                    else if(i==e1&&j==e2)ans+=num;
                }
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%s",c+1);
            for(int j=1;j<=m;j++){
                if(c[j]=='.')mp[i][j]=1,e1=i,e2=j;
            }
        }
        sit[0]=1;
        for(int i=1;i<=12;i++){
            sit[i]=(sit[i-1]<<2);
        }
        work();
        printf("%lld
    ",ans);
        return 0;
    }
    //其实也是背着写了一遍再对着标程改…这一篇是一次AC【这是个伏笔】 

    P2289 [HNOI2004]邮递员

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int m,n,now,lst;
    const int has=299989;
    int sit[12],a[2][300010],head[300010],Next[300010],tot[2];
    struct node{
        int len;
        int c[50];
    }f[2][300010],ans;
    node jia(node a,node b){
        node d;
        int sum=0;
        memset(d.c,0,sizeof(d.c));
        d.len=max(a.len,b.len);
        for(int i=1;i<=d.len;i++){
            sum=sum+a.c[i]+b.c[i];
            d.c[i]=sum%10;
            sum/=10;
        }
        while(sum){
            d.c[++d.len]=sum%10;
            sum/=10;
        }
        return d;
    }
    void ins(int zt,node num){
        int pos=zt%has+1;
        for(int i=head[pos];i;i=Next[i]){
            if(a[now][i]==zt){
                f[now][i]=jia(f[now][i],num);//这个地方写成了jia(f[now][i],num)
                //对,不是f[now][i]=jia(f[now][i],num)…只写了调用函数没有赋值…还以为是高精炸了 
                return;
            }
        }
        Next[++tot[now]]=head[pos],head[pos]=tot[now];
        a[now][tot[now]]=zt,f[now][tot[now]]=num;
    }
    void work(){
        memset(f[now][1].c,0,sizeof(f[now][1].c));
        tot[now]=1,a[now][1]=0,f[now][1].len=1,f[now][1].c[1]=1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=tot[now];j++)a[now][j]<<=2;
            for(int j=1;j<=m;j++){
                lst=now,now^=1;
                memset(head,0,sizeof(head));
                tot[now]=0;
                for(int k=1;k<=tot[lst];k++){
                    node num=f[lst][k];
                    int zt=a[lst][k];
                    int b1=((zt>>(j-1)*2))%4,b2=(zt>>(j*2))%4;
                    if(!b1&&!b2){
                        if(j+1<=m&&i+1<=n)ins(zt+sit[j-1]+sit[j]*2,num);
                    }
                    else if(!b1&&b2){
                        if(j+1<=m)ins(zt,num);
                        if(i+1<=n)ins(zt-sit[j]*b2+sit[j-1]*b2,num);
                    }
                    else if(b1&&!b2){
                        if(i+1<=n)ins(zt,num);
                        if(j+1<=m)ins(zt-sit[j-1]*b1+sit[j]*b1,num);
                    }
                    else if(b1==1&&b2==1){
                        int kl=1;
                        for(int t=j+1;t<=m;t++){
                            if((zt>>(t*2))%4==1)kl++;
                            if((zt>>(t*2))%4==2)kl--;
                            if(!kl){
                                ins(zt-sit[j]-sit[j-1]-sit[t],num);
                                break;
                            }
                        }
                    }
                    else if(b1==2&&b2==2){
                        int kl=1;
                        for(int t=j-2;t>0;t--){//写成j-1一万次…… 
                            if((zt>>(t*2))%4==1)kl--;
                            if((zt>>(t*2))%4==2)kl++;
                            if(!kl){
                                ins(zt-sit[j]*2-sit[j-1]*2+sit[t],num);
                                break;
                            }
                        }
                    }
                    else if(b1==2&&b2==1){
                        ins(zt-sit[j-1]*2-sit[j],num);
                    }
                    else if(i==n&&j==m)ans=jia(ans,num);
                }
            }
        }
    }
    int main()
    {
        scanf("%d%d",&m,&n);
        if(m==1||n==1){//这个特判,一开始打成m==1||n==1 输出0…然后折腾了半天想路径长度去了【?】 然后写成了m==1&&n==1 输出1… 
            printf("1");
            return 0;
        }
        sit[0]=1;
        for(int i=1;i<=11;i++)sit[i]=(sit[i-1]<<2);//一开始跑了n的范围,20,还没意识到炸了…被提醒以后第一反应居然是开long long而不是转成m的范围 
        work();
        ans=jia(ans,ans);
        if(!ans.len){
            printf("0");
            return 0;
        }
        for(int i=ans.len;i>=1;i--){
            printf("%d",ans.c[i]);
        }
        return 0;
    }

    CITY

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,m,now,lst,e1,e2;
    const int has=299989;
    long long ans,f[2][300010];
    int a[2][300010],tot[2],Next[300010],head[300010],sit[15];
    char mp[15][15],s[15];
    void ins(int zt,long long num){
        int pos=zt%has+1;
        for(int i=head[pos];i;i=Next[i]){
            if(a[now][i]==zt){
                f[now][i]+=num;
                return;
            }
        }
        Next[++tot[now]]=head[pos],head[pos]=tot[now];
        a[now][tot[now]]=zt,f[now][tot[now]]=num;
    }
    void work(){
        tot[now]=1,a[now][1]=0,f[now][1]=1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=tot[now];j++)a[now][j]<<=2;
            for(int j=1;j<=m;j++){
                lst=now,now^=1;
                memset(head,0,sizeof(head));
                tot[now]=0;
                for(int k=1;k<=tot[lst];k++){
                    long long num=f[lst][k];
                    int zt=a[lst][k],b1=(zt>>((j-1)*2))%4,b2=(zt>>(j*2))%4;
                    if(mp[i][j]=='#'){
                        if(!b1&&!b2)ins(zt,num);
                    }
                    else if(!b1&&!b2){
                        if(mp[i][j]=='.'&&(mp[i+1][j]=='|'||mp[i+1][j]=='.')&&(mp[i][j+1]=='-'||mp[i][j+1]=='.')){
                            ins(zt+sit[j-1]+sit[j]*2,num);
                        }
                    }
                    else if(b1&&!b2){
                        if((mp[i+1][j]=='.'||mp[i+1][j]=='|')&&mp[i][j]!='-'&&mp[i][j]!='|')ins(zt,num);
                        if((mp[i][j+1]=='.'||mp[i][j+1]=='-')&&mp[i][j]!='|')ins(zt-sit[j-1]*b1+sit[j]*b1,num);
                    }
                    else if(!b1&&b2){
                        if((mp[i][j+1]=='.'||mp[i][j+1]=='-')&&mp[i][j]!='-'&&mp[i][j]!='|')ins(zt,num);
                        if((mp[i+1][j]=='.'||mp[i+1][j]=='|')&&mp[i][j]!='-')ins(zt-sit[j]*b2+sit[j-1]*b2,num);
                    }
                    else if(b1==1&&b2==1){
                        if(mp[i][j]!='-'&&mp[i][j]!='|'){
                            int kl=1;
                            for(int t=j+1;t<=m;t++){
                                if((zt>>(t*2))%4==1)kl++;
                                if((zt>>(t*2))%4==2)kl--;
                                if(!kl){
                                    ins(zt-sit[j]-sit[j-1]-sit[t],num);
                                    break;
                                }
                            }
                        }
                    }
                    else if(b1==2&&b2==2){
                        if(mp[i][j]!='-'&&mp[i][j]!='|'){
                            int kl=1;
                            for(int t=j-2;t>0;t--){
                                if((zt>>(t*2))%4==1)kl--;
                                if((zt>>(t*2))%4==2)kl++;
                                if(!kl){
                                    ins(zt-sit[j]*2-sit[j-1]*2+sit[t],num);
                                    break;
                                }
                            }
                        }
                    }
                    else if(b1==2&&b2==1){
                        if(mp[i][j]!='-'&&mp[i][j]!='|'){
                            ins(zt-sit[j-1]*2-sit[j],num);
                        }
                    }
                    else if(i==e1&&j==e2&&mp[i][j]!='-'&&mp[i][j]!='|'){//伏笔还是要收的,久等了【大雾】 
                        // 上一道题没有用到e1e2,第二道题我又是照着标程改的,然后完美忘记,从(n,m)的地方累计答案去了
                        //居然还有90分,折腾了半天细节,结果是这里… 
                        ans+=num;
                    }
                }
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            for(int j=1;j<=m;j++){
                mp[i][j]=s[j];
                if(j==1||j==m){
                    if(mp[i][j]=='-'){
                        printf("0");
                        return 0;
                    }
                }
                if(i==1||i==n){
                    if(mp[i][j]=='|'){
                        printf("0");
                        return 0;
                    }
                }
                if(mp[i][j]!='#')e1=i,e2=j;//伏 笔 回 收 ,欠下的总是要还的 
            }
        }
        sit[0]=1;
        for(int i=1;i<=13;i++)sit[i]=sit[i-1]<<2;
        work();
        printf("%lld",ans);
        return 0;
    }

    今天也在非常认真地怀疑自己的智商

  • 相关阅读:
    二叉排序树 常用函数小结
    二叉树的应用:二叉排序树的删除
    剑指 Offer 32
    剑指 Offer 32
    剑指 Offer 68
    剑指 Offer 28. 对称的二叉树 做题小结
    正则表达式不要背
    剑指 Offer 55
    LeetCode226. 翻转二叉树 做题小结
    Tools | 编程IED/编译器
  • 原文地址:https://www.cnblogs.com/chloris/p/11260955.html
Copyright © 2011-2022 走看看