[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
原文地址:https://www.cnblogs.com/czllgzmzl/p/5495227.html