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;
    }

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

  • 相关阅读:
    Rotation Kinematics
    离职 mark
    PnP 问题方程怎么列?
    DSO windowed optimization 代码 (4)
    Adjoint of SE(3)
    IMU 预积分推导
    DSO windowed optimization 代码 (3)
    DSO windowed optimization 代码 (2)
    OKVIS 代码框架
    DSO windowed optimization 代码 (1)
  • 原文地址:https://www.cnblogs.com/chloris/p/11260955.html
Copyright © 2011-2022 走看看