zoukankan      html  css  js  c++  java
  • [ZOJ3213] Beautiful Meadow

      插头DP。。。网格图,有障碍,格子上有权值,求总权值最大的简单路径。

      因为路径的起始点不确定。。所以多开一维表示当前已经有多少个独立插头。。

      只要不合并相同的联通块,并且已经用了2个独立插头,那就是一条简单路径了。。。

      需要特判路径上只有一个点的情况。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #define ll long long
      6 using namespace std;
      7 const int modd=5233,maxzt=123333;
      8 struct zs1{
      9     struct zs{
     10         int pre;ll too;
     11     }e[maxzt];int tot,last[modd];
     12     int f[maxzt];ll zt[maxzt];
     13     inline int get(ll v){
     14         int i,x=v%modd;
     15         for(i=last[x];i&&e[i].too!=v;i=e[i].pre);
     16         if(i)return i;
     17         e[++tot].too=v,e[tot].pre=last[x],last[x]=tot,
     18         f[tot]=0,zt[tot]=v;
     19         return tot;
     20     }
     21 }hm[2][3];
     22 
     23 int i,j,k,n,m;
     24 bool can[23][23];int val[23][23];
     25 int mp[9],id[9];bool u[9];
     26 
     27 inline void clr(bool now,int num){
     28     memset(hm[now][num].last,0,modd<<2);
     29     hm[now][num].tot=0;
     30 }
     31 inline void upd(int &a,int b){if(b>a)a=b;}
     32 inline void decode(ll x){
     33     for(int i=m;i>=0;i--)mp[i]=x&7,x>>=3;
     34 }
     35 inline ll encode(){
     36     int i,tt=0;ll x=0;
     37     memset(u,0,9);
     38     for(i=0;i<=m;mp[i]=id[mp[i]],x=x<<3|mp[i],i++)
     39         if(!u[mp[i]]&&mp[i]>0)u[mp[i]]=1,id[mp[i]]=++tt;
     40     return x;
     41 }
     42 inline void dp_blank(int x,int y,bool pre){
     43     int i,left,up,f;ll zt;bool now=pre^1;
     44     for(int num=0;num<=2;num++){
     45 //        printf("    %d,%d %d
    ",x,y,num);
     46         clr(now,num);
     47         for(i=1;i<=hm[pre][num].tot;i++){
     48             zt=hm[pre][num].zt[i],f=hm[pre][num].f[i];
     49             if(y==1)zt>>=3;
     50             decode(zt);
     51 //            for(int j=0;j<=m;j++)printf(" %d",mp[j]);printf("    %d    zt:%lld
    ",f,zt);
     52             left=mp[y-1],up=mp[y];
     53             if(left&&up&&left!=up){
     54                 mp[y-1]=mp[y]=0;
     55                 for(int j=0;j<=m;j++)if(mp[j]==up){mp[j]=left;break;}
     56                 upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
     57             }
     58             if(!left&&!up){
     59                 upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f );
     60                 if(can[x+1][y]&&can[x][y+1])
     61                     mp[y-1]=mp[y]=7,
     62                     upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
     63             }
     64             if((!left)^(!up)){
     65                 int j=left|up;
     66                 if(can[x+1][y])
     67                     mp[y-1]=j,mp[y]=0,
     68                     upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
     69                 if(can[x][y+1])
     70                     mp[y-1]=0,mp[y]=j,
     71                     upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
     72             }
     73         }
     74         if(num>0)
     75             for(i=1;i<=hm[pre][num-1].tot;i++){
     76                 zt=hm[pre][num-1].zt[i],f=hm[pre][num-1].f[i];
     77                 if(y==1)zt>>=3;
     78                 decode(zt);
     79 //                for(int j=0;j<=m;j++)printf(" %d",mp[j]);printf("    (dl) %d   zt:%lld
    ",f,zt);
     80                 left=mp[y-1],up=mp[y];
     81                 if(!left&&!up){
     82                     if(can[x+1][y])
     83                         mp[y-1]=7,mp[y]=0,
     84                         upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
     85                     if(can[x][y+1])
     86                         mp[y-1]=0,mp[y]=7,
     87                         upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );//,printf("   %lld %d
    ",encode(),y);
     88                 }
     89                 if((!left)^(!up))
     90                     mp[y-1]=mp[y]=0,
     91                     upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
     92             }
     93     }
     94 }
     95 inline void dp_bar(int x,int y,bool pre){
     96     int i,left,up,f;ll zt;bool now=pre^1;
     97     for(int num=0;num<=2;num++){
     98         clr(now,num);
     99         for(i=1;i<=hm[pre][num].tot;i++){
    100             zt=hm[pre][num].zt[i],f=hm[pre][num].f[i];
    101             if(y==1)zt>>=3;
    102             decode(zt),
    103             left=mp[y-1],up=mp[y];
    104             if(!left&&!up)
    105                 upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
    106         }
    107     }
    108 }
    109 
    110 int ra;char rx;
    111 inline int read(){
    112     rx=getchar(),ra=0;
    113     while(rx<'0'||rx>'9')rx=getchar();
    114     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
    115 }
    116 int main(){
    117     for(int T=read();T;T--){
    118         n=read(),m=read();
    119         memset(can,0,sizeof(can));
    120         int ans=0;
    121         for(i=1;i<=n;i++)for(j=1;j<=m;j++)val[i][j]=read(),can[i][j]=val[i][j]!=0,ans=max(ans,val[i][j]);
    122         bool pre=0,now=1;
    123         clr(pre,0),clr(pre,1),clr(pre,2);
    124         hm[pre][0].f[ hm[pre][0].get(0) ]=0;
    125         for(i=1;i<=n;i++)for(j=1;j<=m;j++,swap(pre,now))
    126             if(can[i][j])dp_blank(i,j,pre);else dp_bar(i,j,pre);
    127         for(i=1;i<=hm[pre][2].tot;i++)
    128             upd(ans,hm[pre][2].f[i]);
    129         printf("%d
    ",ans);
    130     }
    131     return 0;
    132 }
    View Code
  • 相关阅读:
    数的划分终极版--背包法解决各类数的划分
    128.最长公共子序列
    整数划分类型题目--专练
    主函数
    LED类代码
    APM2.8地面站下载地址
    多文件函数调用
    流水灯
    APM的3DR无线数传的安装和调试
    闪烁的LED灯
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5495227.html
Copyright © 2011-2022 走看看