• 插头DP


    HDU1693 Eat the Trees

    不用分左右插头的DP。关键就是逐格递推。行与行之间的转移看轮廓线发现很happy。

     1 int a[13][13];
     2 ll dp[13][13][1<<15];
     3 int main()
     4 {
     5     freopen("input.txt","r",stdin);
     6     freopen("output.txt","w",stdout);
     7     int T=read(),cs=0;
     8     while(T--)
     9     {
    10         int n=read(),m=read();
    11         for1(i,n)for1(j,m)a[i][j]=read();
    12         dp[0][m][0]=1;
    13         for1(i,n)
    14          {
    15              for0(j,(1<<m)-1)dp[i][0][j<<1]=dp[i-1][m][j];
    16              for1(j,m)
    17               for0(k,(1<<(m+1))-1)
    18                {
    19                    int x=1<<(j-1),y=1<<j;
    20                    if(a[i][j])
    21                    {
    22                        dp[i][j][k]=dp[i][j-1][k^x^y];
    23                        if(((k&x)!=0)^((k&y)!=0))dp[i][j][k]+=dp[i][j-1][k];
    24                    }else dp[i][j][k]=(!(k&x)&&!(k&y))*dp[i][j-1][k];
    25                }
    26          }
    27         printf("Case %d: There are %lld ways to eat the trees.
    ",++cs,dp[n][m][0]);
    28     }
    29     return 0;
    30 }
    View Code

     URAL1519 Formula 1

    真正的插头DP来了。发现很好理解, 写起来略蛋疼。hash表的写法各有各的。注意位运算的优先级。

     1 int n,m,head[2][maxn],tot[2],b[20],now,pre;
     2 bool a[20][20];
     3 ll dp[2][maxn];
     4 struct edge{int go,id,next;}e[2][maxn];
     5 inline void add(int v,ll w)
     6 {
     7     int z=v%mod;
     8     for5(now,i,z)if(y==v){dp[now][i]+=w;return;}
     9     e[now][++tot[now]]=(edge){v,z,head[now][z]};head[now][z]=tot[now];
    10     dp[now][tot[now]]=w;
    11 }
    12 int main()
    13 {
    14     freopen("input.txt","r",stdin);
    15     freopen("output.txt","w",stdout);
    16     for0(i,20)b[i]=i<<1;
    17     now=0;pre=1;
    18     n=read();m=read();int xx,yy;ll ans=0;
    19     for1(i,n)for1(j,m)
    20     {
    21         char ch=getchar();while(ch!='*'&&ch!='.')ch=getchar();a[i][j]=ch=='.';
    22         if(a[i][j])xx=i,yy=j;
    23     }
    24     add(0,1);
    25     for1(i,n)
    26     {
    27      for1(j,tot[now])e[now][j].go<<=2;
    28      for1(j,m)
    29       {
    30         swap(now,pre);
    31         for1(k,tot[now])head[now][e[now][k].id]=0;tot[now]=0;
    32         for1(k,tot[pre])
    33         {
    34             int v=e[pre][k].go,x=v>>b[j-1]&3,y=v>>b[j]&3;ll w=dp[pre][k];
    35             if(!a[i][j]){if(x+y==0)add(v,w);}
    36             else if(x+y==0)
    37             {
    38                 if(!a[i][j+1]||!a[i+1][j])continue;
    39                 add(v^(1<<b[j-1])^(2<<b[j]),w);
    40             }
    41             else if(!x&&y)
    42             {
    43                 if(a[i][j+1])add(v,w);
    44                 if(a[i+1][j])add(v^(y<<b[j-1])^(y<<b[j]),w);
    45             }else if(x&&!y)
    46             {
    47                 if(a[i+1][j])add(v,w);
    48                 if(a[i][j+1])add(v^(x<<b[j-1])^(x<<b[j]),w);
    49             }else if(x+y==2)
    50             {
    51                 int t1=1,t2;
    52                 for2(l,j+1,m)
    53                 {
    54                     t2=v>>b[l]&3;
    55                     if(t2==1)t1++;
    56                     if(t2==2)t1--;
    57                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))-(1<<b[l]),w);break;}
    58                 }
    59             }else if(x+y==4)
    60             {
    61                 int t1=1,t2;
    62                 for3(l,j-2,0)
    63                 {
    64                     t2=v>>b[l]&3;
    65                     if(t2==2)t1++;
    66                     if(t2==1)t1--;
    67                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))+(1<<b[l]),w);break;}
    68                 }
    69             }else if(x==2&&y==1)add(v^(x<<b[j-1])^(y<<b[j]),w);
    70              else if(i==xx&&j==yy)ans+=w;
    71         }
    72       }
    73     }
    74     cout<<ans<<endl;
    75     return 0;
    76 }
    View Code

     HDU1964 Pipes

    套上面的代码,把取和改成取min。什么?你说读入?读入优化大法好。直接过滤无用字符。

     1 int n,m,head[2][maxn],tot[2],b[20],now,pre,dp[2][maxn],a[20][20],c[20][20];
     2 struct edge{int go,id,next;}e[2][maxn];
     3 inline void add(int v,int w)
     4 {
     5     int z=v%mod;
     6     for5(now,i,z)if(y==v){dp[now][i]=min(dp[now][i],w);return;}
     7     e[now][++tot[now]]=(edge){v,z,head[now][z]};head[now][z]=tot[now];
     8     dp[now][tot[now]]=w;
     9 }
    10 inline bool check(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m;}
    11 int main()
    12 {
    13     freopen("input.txt","r",stdin);
    14     freopen("output.txt","w",stdout);
    15     for0(i,20)b[i]=i<<1;
    16     int T=read();
    17     while(T--)
    18     {
    19     now=0;pre=1;
    20     n=read();m=read();int ans=inf;
    21     memset(a,0,sizeof(a));memset(c,0,sizeof(c));
    22     for2(i,2,2*n)for1(j,i&1?m:m-1)i&1?c[i>>1][j]=read():a[i>>1][j]=read();
    23     add(0,0);
    24     for1(i,n)
    25     {
    26      for1(j,tot[now])e[now][j].go<<=2;
    27      for1(j,m)
    28       {
    29         swap(now,pre);
    30         for1(k,tot[now])head[now][e[now][k].id]=0;tot[now]=0;
    31         for1(k,tot[pre])
    32         {
    33             int v=e[pre][k].go,x=v>>b[j-1]&3,y=v>>b[j]&3,w=dp[pre][k];
    34             if(x+y==0)
    35             {
    36                 if(!check(i,j+1)||!check(i+1,j))continue;
    37                 add(v^(1<<b[j-1])^(2<<b[j]),w+c[i][j]+a[i][j]);
    38             }
    39             else if(!x&&y)
    40             {
    41                 if(check(i,j+1))add(v,w+a[i][j]);
    42                 if(check(i+1,j))add(v^(y<<b[j-1])^(y<<b[j]),w+c[i][j]);
    43             }else if(x&&!y)
    44             {
    45                 if(check(i+1,j))add(v,w+c[i][j]);
    46                 if(check(i,j+1))add(v^(x<<b[j-1])^(x<<b[j]),w+a[i][j]);
    47             }else if(x+y==2)
    48             {
    49                 int t1=1,t2;
    50                 for2(l,j+1,m)
    51                 {
    52                     t2=v>>b[l]&3;
    53                     if(t2==1)t1++;
    54                     if(t2==2)t1--;
    55                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))-(1<<b[l]),w);break;}
    56                 }
    57             }else if(x+y==4)
    58             {
    59                 int t1=1,t2;
    60                 for3(l,j-2,0)
    61                 {
    62                     t2=v>>b[l]&3;
    63                     if(t2==2)t1++;
    64                     if(t2==1)t1--;
    65                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))+(1<<b[l]),w);break;}
    66                 }
    67             }else if(x==2&&y==1)add(v^(x<<b[j-1])^(y<<b[j]),w);
    68              else if(i==n&&j==m)ans=min(ans,w);
    69         }
    70       }
    71     }
    72     cout<<ans<<endl;
    73     }
    74     return 0;
    75 }
    View Code

     POJ1739 Tony's Tour

    套上上面的代码,强行把欧拉路改成欧拉回路,在棋盘下面加两行即可。

     1 int n,m,head[2][maxn],tot[2],b[20],now,pre;
     2 bool a[20][20];
     3 ll dp[2][maxn];
     4 struct edge{int go,id,next;}e[2][maxn];
     5 inline void add(int v,ll w)
     6 {
     7     int z=v%mod;
     8     for5(now,i,z)if(y==v){dp[now][i]+=w;return;}
     9     e[now][++tot[now]]=(edge){v,z,head[now][z]};head[now][z]=tot[now];
    10     dp[now][tot[now]]=w;
    11 }
    12 int main()
    13 {
    14     freopen("input.txt","r",stdin);
    15     freopen("output.txt","w",stdout);
    16     for0(i,20)b[i]=i<<1;
    17     now=0;pre=1;
    18     while(1)
    19     {
    20     n=read();m=read();ll ans=0;
    21     memset(a,0,sizeof(a));
    22     if(!n&&!m)break;
    23     for1(i,n)for1(j,m)
    24     {
    25         char ch=getchar();while(ch!='#'&&ch!='.')ch=getchar();a[i][j]=ch=='.';
    26     }
    27     for1(i,m)if(i==1||i==m)a[n+1][i]=1;else a[n+1][i]=0;
    28     for1(i,m)a[n+2][i]=1;
    29     n+=2;
    30     add(0,1);
    31     for1(i,n)
    32     {
    33      for1(j,tot[now])e[now][j].go<<=2;
    34      for1(j,m)
    35       {
    36         swap(now,pre);
    37         for1(k,tot[now])head[now][e[now][k].id]=0;tot[now]=0;
    38         for1(k,tot[pre])
    39         {
    40             int v=e[pre][k].go,x=v>>b[j-1]&3,y=v>>b[j]&3;ll w=dp[pre][k];
    41             if(!a[i][j]){if(x+y==0)add(v,w);}
    42             else if(x+y==0)
    43             {
    44                 if(!a[i][j+1]||!a[i+1][j])continue;
    45                 add(v^(1<<b[j-1])^(2<<b[j]),w);
    46             }
    47             else if(!x&&y)
    48             {
    49                 if(a[i][j+1])add(v,w);
    50                 if(a[i+1][j])add(v^(y<<b[j-1])^(y<<b[j]),w);
    51             }else if(x&&!y)
    52             {
    53                 if(a[i+1][j])add(v,w);
    54                 if(a[i][j+1])add(v^(x<<b[j-1])^(x<<b[j]),w);
    55             }else if(x+y==2)
    56             {
    57                 int t1=1,t2;
    58                 for2(l,j+1,m)
    59                 {
    60                     t2=v>>b[l]&3;
    61                     if(t2==1)t1++;
    62                     if(t2==2)t1--;
    63                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))-(1<<b[l]),w);break;}
    64                 }
    65             }else if(x+y==4)
    66             {
    67                 int t1=1,t2;
    68                 for3(l,j-2,0)
    69                 {
    70                     t2=v>>b[l]&3;
    71                     if(t2==2)t1++;
    72                     if(t2==1)t1--;
    73                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))+(1<<b[l]),w);break;}
    74                 }
    75             }else if(x==2&&y==1)add(v^(x<<b[j-1])^(y<<b[j]),w);
    76              else if(i==n&&j==m)ans+=w;
    77         }
    78       }
    79     }
    80     cout<<ans<<endl;
    81     }
    82     return 0;
    83 }
    View Code

     HDU3377 Plan

    套上上面的代码。。。卧槽这都什么题啊。。。求路径补成回路,在外面加一圈权值非常大的。

     1 int n,m,head[2][maxn],tot[2],b[20],now,pre;
     2 ll a[20][20],dp[2][maxn];
     3 struct edge{int go,id,next;}e[2][maxn];
     4 inline void add(int v,ll w)
     5 {
     6     int z=v%mod;
     7     for5(now,i,z)if(y==v){dp[now][i]=max(dp[now][i],w);return;}
     8     e[now][++tot[now]]=(edge){v,z,head[now][z]};head[now][z]=tot[now];
     9     dp[now][tot[now]]=w;
    10 }
    11 inline bool check(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m;}
    12 int main()
    13 {
    14     freopen("input.txt","r",stdin);
    15     freopen("output.txt","w",stdout);
    16     for0(i,20)b[i]=i<<1;int cs=0;
    17     while(scanf("%d%d",&n,&m)!=EOF)
    18     {
    19     now=0;pre=1;
    20     ll ans=-inf;
    21     memset(a,0,sizeof(a));
    22     n+=2;m+=2;
    23     for1(i,m)a[1][i]=inf;
    24     for1(i,n)a[i][m]=inf;
    25     a[2][1]=a[n][m-1]=inf;
    26     for2(i,2,m-1)a[2][i]=-inf;
    27     for2(i,2,n-1)a[i][m-1]=-inf;
    28     for2(i,3,n)for1(j,m-2)a[i][j]=read();
    29     //for1(i,n)for1(j,m)printf("%I64d%c",a[i][j],j==m?'
    ':' ');
    30     memset(head,0,sizeof(head));tot[0]=tot[1]=0;
    31     add(0,0);
    32     for1(i,n)
    33     {
    34      for1(j,tot[now])e[now][j].go<<=2;
    35      for1(j,m)
    36       {
    37         swap(now,pre);
    38         for1(k,tot[now])head[now][e[now][k].id]=0;tot[now]=0;
    39         for1(k,tot[pre])
    40         {
    41             int v=e[pre][k].go,x=v>>b[j-1]&3,y=v>>b[j]&3;ll w=dp[pre][k];
    42             if(x+y==0)
    43             {
    44                 add(v,w);
    45                 if(!check(i,j+1)||!check(i+1,j))continue;
    46                 add(v^(1<<b[j-1])^(2<<b[j]),w+a[i][j]);
    47             }
    48             else if(!x&&y)
    49             {
    50                 if(check(i,j+1))add(v,w+a[i][j]);
    51                 if(check(i+1,j))add(v^(y<<b[j-1])^(y<<b[j]),w+a[i][j]);
    52             }else if(x&&!y)
    53             {
    54                 if(check(i+1,j))add(v,w+a[i][j]);
    55                 if(check(i,j+1))add(v^(x<<b[j-1])^(x<<b[j]),w+a[i][j]);
    56             }else if(x+y==2)
    57             {
    58                 int t1=1,t2;
    59                 for2(l,j+1,m)
    60                 {
    61                     t2=v>>b[l]&3;
    62                     if(t2==1)t1++;
    63                     if(t2==2)t1--;
    64                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))-(1<<b[l]),w+a[i][j]);break;}
    65                 }
    66             }else if(x+y==4)
    67             {
    68                 int t1=1,t2;
    69                 for3(l,j-2,0)
    70                 {
    71                     t2=v>>b[l]&3;
    72                     if(t2==2)t1++;
    73                     if(t2==1)t1--;
    74                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))+(1<<b[l]),w+a[i][j]);break;}
    75                 }
    76             }else if(x==2&&y==1)add(v^(x<<b[j-1])^(y<<b[j]),w+a[i][j]);
    77              else if(i==n&&j==m)ans=max(ans,w+a[i][j]);
    78         }
    79       }
    80     }
    81     printf("Case %d: ",++cs);cout<<(ans-(ll)(m+n+1)*inf)<<endl;
    82     }
    83     return 0;
    84 }
    View Code

     SCOI2011地板

    这才叫插头DP题嘛!用0表示此处无插头,1表示有但是还需要转弯,2表示有并且不需要转弯。

    转移:

    00->01|10|22

    10->20|01

    01->10|02

    20->00|02

    02->00|20

    11->00

     1 int n,m,head[2][maxn],tot[2],b[20],now,pre;
     2 bool a[101][101];
     3 ll dp[2][maxn];
     4 struct edge{int go,id,next;}e[2][maxn];
     5 inline void add(int v,ll w)
     6 {
     7     //cout<<v<<' '<<w<<endl;
     8     int z=v%p;
     9     for5(now,i,z)if(y==v){(dp[now][i]+=w)%=mod;return;}
    10     e[now][++tot[now]]=(edge){v,z,head[now][z]};head[now][z]=tot[now];
    11     dp[now][tot[now]]=w;
    12 }
    13 int main()
    14 {
    15     freopen("input.txt","r",stdin);
    16     freopen("output.txt","w",stdout);
    17     for0(i,20)b[i]=i<<1;
    18     n=read();m=read();
    19     for1(i,n)for1(j,m)
    20     {
    21         char ch=getchar();while(ch!='*'&&ch!='_')ch=getchar();
    22         if(n>m)a[i][j]=ch=='_';else a[j][i]=ch=='_';
    23     }
    24     if(n<m)swap(n,m);
    25     now=0;pre=1;
    26     add(0,1);
    27     for1(i,n)
    28     {
    29         //cout<<tot[now]<<endl;
    30         for1(j,tot[now])e[now][j].go<<=2;
    31         for1(j,m)
    32         {
    33             swap(now,pre);
    34             for1(k,tot[now])head[now][e[now][k].id]=0;tot[now]=0;
    35             for1(k,tot[pre])
    36             {
    37                 int v=e[pre][k].go,x=v>>b[j-1]&3,y=v>>b[j]&3;ll w=dp[pre][k];
    38                 if(!a[i][j]){if(x+y==0)add(v,w);}
    39                 else if(x+y==0)
    40                 {
    41                     if(a[i+1][j])add(v^(1<<b[j-1]),w);
    42                     if(a[i][j+1])add(v^(1<<b[j]),w);
    43                     if(a[i+1][j]&&a[i][j+1])add(v^(2<<b[j-1])^(2<<b[j]),w);
    44                 }else if(x==1&&!y)
    45                 {
    46                     if(a[i+1][j])add(v+(1<<b[j-1]),w);
    47                     if(a[i][j+1])add(v^(1<<b[j-1])^(1<<b[j]),w);
    48                 }else if(!x&&y==1)
    49                 {
    50                     if(a[i][j+1])add(v+(1<<b[j]),w);
    51                     if(a[i+1][j])add(v^(1<<b[j-1])^(1<<b[j]),w);
    52                 }else if(x==2&&!y)
    53                 {
    54                     add(v^(2<<b[j-1]),w);
    55                     if(a[i][j+1])add(v^(2<<b[j-1])^(2<<b[j]),w);
    56                 }else if(!x&&y==2)
    57                 {
    58                     add(v^(2<<b[j]),w);
    59                     if(a[i+1][j])add(v^(2<<b[j-1])^(2<<b[j]),w);
    60                 }else if(x==1&&y==1)
    61                 {
    62                     add(v^(1<<b[j-1])^(1<<b[j]),w);
    63                 }
    64             }
    65         }
    66     }
    67     cout<<(tot[now]?dp[now][1]:0)<<endl;
    68     return 0;
    69 }
    View Code

    HNOI2004邮递员

    插头DP求回路。加个高精度。AC了之后发现时光机说这题有点问题。Orz

      1 int n,m,head[2][maxm],tot[2],b[20],now,pre;
      2 bool a[20][20];
      3 struct edge{int go,id,next;}e[2][maxn];
      4 struct bignum
      5 {
      6     int x[10],n;
      7     void init(int b)
      8     {
      9         memset(x,0,sizeof(x)); 
     10         x[n=1]=b;
     11     }
     12     void rebuild()
     13     {
     14         for(int i=1;i<=n||x[i];i++)
     15         {
     16             x[i+1]+=x[i]/bs;
     17             x[i]%=bs;
     18             if(i>n)n=i;
     19         }
     20     }    
     21     void operator +=(bignum b)
     22     {
     23         n=max(n,b.n);
     24         for1(i,n)x[i]+=b.x[i];
     25         this->rebuild();
     26     }
     27     void print()
     28     {
     29         printf("%d",x[n]);
     30         for3(i,n-1,1)printf("%04d",x[i]);
     31         printf("
    ");
     32     }
     33     void operator *=(int b)
     34     {
     35         for1(i,n)x[i]*=b;
     36         this->rebuild();
     37     }
     38 }dp[2][maxn];
     39 inline void add(int v,bignum w)
     40 {
     41     int z=v%mod;
     42     for5(now,i,z)if(y==v){dp[now][i]+=w;return;}
     43     e[now][++tot[now]]=(edge){v,z,head[now][z]};head[now][z]=tot[now];
     44     dp[now][tot[now]]=w;
     45 }
     46 int main()
     47 {
     48     freopen("input.txt","r",stdin);
     49     freopen("output.txt","w",stdout);
     50     for0(i,20)b[i]=i<<1;
     51     now=0;pre=1;
     52     n=read();m=read();if(n<m)swap(n,m);
     53     if(m==1){printf("%d
    ",1);return 0;}
     54     for1(i,n)for1(j,m)a[i][j]=1;
     55     bignum ans;ans.init(1);
     56     add(0,ans);
     57     ans.init(0);
     58     for1(i,n)
     59     {
     60      for1(j,tot[now])e[now][j].go<<=2;
     61      for1(j,m)
     62       {
     63         swap(now,pre);
     64         for1(k,tot[now])head[now][e[now][k].id]=0;tot[now]=0;
     65         for1(k,tot[pre])
     66         {
     67             int v=e[pre][k].go,x=v>>b[j-1]&3,y=v>>b[j]&3;bignum w=dp[pre][k];
     68             if(!a[i][j]){if(x+y==0)add(v,w);}
     69             else if(x+y==0)
     70             {
     71                 if(!a[i][j+1]||!a[i+1][j])continue;
     72                 add(v^(1<<b[j-1])^(2<<b[j]),w);
     73             }
     74             else if(!x&&y)
     75             {
     76                 if(a[i][j+1])add(v,w);
     77                 if(a[i+1][j])add(v^(y<<b[j-1])^(y<<b[j]),w);
     78             }else if(x&&!y)
     79             {
     80                 if(a[i+1][j])add(v,w);
     81                 if(a[i][j+1])add(v^(x<<b[j-1])^(x<<b[j]),w);
     82             }else if(x+y==2)
     83             {
     84                 int t1=1,t2;
     85                 for2(l,j+1,m)
     86                 {
     87                     t2=v>>b[l]&3;
     88                     if(t2==1)t1++;
     89                     if(t2==2)t1--;
     90                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))-(1<<b[l]),w);break;}
     91                 }
     92             }else if(x+y==4)
     93             {
     94                 int t1=1,t2;
     95                 for3(l,j-2,0)
     96                 {
     97                     t2=v>>b[l]&3;
     98                     if(t2==2)t1++;
     99                     if(t2==1)t1--;
    100                     if(!t1){add((v^(x<<b[j-1])^(y<<b[j]))+(1<<b[l]),w);break;}
    101                 }
    102             }else if(x==2&&y==1)add(v^(x<<b[j-1])^(y<<b[j]),w);
    103              else if(i==n&&j==m)ans+=w; 
    104              //if(x==1&&y==2)add(v^(x<<b[j-1])^(y<<b[j]),w);
    105         }
    106       }
    107     }
    108     ans*=2;
    109     ans.print();
    110     return 0;
    111 }
    View Code
  • 相关阅读:
    npm version patch
    nginx 操作
    基于 Vue CLI 组件库封装,按需加载实现
    nginx 配置文件路径获取
    Laravel 生产资源路由并指定模型
    base.js,通用js方法,Js方法封装
    jquery.params.js,Jquery获取页面参数,js获取页面参数
    layui使用,LayUI select不显示,LayUI文件上传,Layui自定义校验规则
    Layer弹窗消息封装,Layer消息提示封装,Layer使用
    Html跨域js封装,前端页面跨域js,postMessage实现跨域
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4391771.html
Copyright © 2020-2023  润新知