标签:
插头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\n",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\n",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\n",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\n",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\n",ans); 130 } 131 return 0; 132 }
标签:
原文地址:http://www.cnblogs.com/czllgzmzl/p/5495227.html