1. 程式人生 > 實用技巧 >CodeForces - 762D Maximum path (插頭dp)

CodeForces - 762D Maximum path (插頭dp)

題目連結

題意:一個3*n的帶權矩陣,問從左上角走到右下角所經過路徑的最大權值和

正解貌似是找規律+dp,不過我沒看出規律來就直接插頭dp搞了,程式碼很長雖然都是套路。。。

唯一要注意的是這道題有起點和終點,我一直在糾結從起點和終點出發的應該是左插頭還是右插頭,後來乾脆兩個都放進去試試,只要有一種組合是正確的即可,剩下的就是通過括號表示法來保證不產生迴路就行了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=1e5+10;
 5 const ll inf=0x3f3f3f3f3f3f3f3fll;
6 int a[N][5],n,m,sx,sy,tx,ty; 7 struct Hashmap { 8 static const int N=1e5+10; 9 int hd[N],nxt[N],fa[N],tot; 10 int p[N]; 11 ll q[N]; 12 Hashmap() {memset(hd,-1,sizeof hd),tot=0;} 13 void clear() {for(int i=0; i<tot; ++i)hd[fa[i]]=-1; tot=0;} 14 ll& operator[](int x) {
15 int u=x%N; 16 for(int i=hd[u]; ~i; i=nxt[i])if(p[i]==x)return q[i]; 17 nxt[tot]=hd[u],fa[tot]=u,p[tot]=x,q[tot]=~inf,hd[u]=tot; 18 return q[tot++]; 19 } 20 int count(int x) { 21 int u=x%N; 22 for(int i=hd[u]; ~i; i=nxt[i])if(p[i]==x)return 1;
23 return 0; 24 } 25 } dp[2]; 26 int getl(int S,int j) {return S>>((j-1)<<1)&3;} 27 int getu(int S,int j) {return S>>(j<<1)&3;} 28 int trans(int S,int j,int d,int r) {return (S&~(15<<((j-1)<<1)))|(d<<((j-1)<<1))|(r<<(j<<1));} 29 int flip(int S,int j) {return S^(3<<(j<<1));} 30 int linkll(int S,int j) { 31 S=trans(S,j,0,0); 32 for(int k=j+1,c=1; k<=m; ++k) { 33 if(getu(S,k)==1)++c; 34 else if(getu(S,k)==2)--c; 35 if(c==0)return flip(S,k); 36 } 37 return S; 38 } 39 int linkrr(int S,int j) { 40 S=trans(S,j,0,0); 41 for(int k=j-2,c=1; k>=0; --k) { 42 if(getu(S,k)==2)++c; 43 else if(getu(S,k)==1)--c; 44 if(c==0)return flip(S,k); 45 } 46 return S; 47 } 48 void upd(ll& t,ll x) {if(x>t)t=x;} 49 ll solve() { 50 upd(dp[0][0],0); 51 int f=0; 52 for(int i=1; i<=n; ++i) 53 for(int j=1; j<=m; ++j,f^=1) { 54 Hashmap &F=dp[f],&G=dp[f^1]; 55 G.clear(); 56 for(int k=0; k<F.tot; ++k) { 57 int S=F.p[k]; 58 ll g=F.q[k]; 59 if(j==1) {if(getl(S,m+1))continue; S<<=2;} 60 int l=getl(S,j),u=getu(S,j); 61 if(i==sx&&j==sy) { 62 if(l)upd(G[trans(S,j,0,0)],g+a[i][j]); 63 else upd(G[trans(S,j,1,0)],g+a[i][j]),upd(G[trans(S,j,2,0)],g+a[i][j]); 64 } else if(i==tx&&j==ty) { 65 if(u)upd(G[trans(S,j,0,0)],g+a[i][j]); 66 else upd(G[trans(S,j,0,1)],g+a[i][j]),upd(G[trans(S,j,0,2)],g+a[i][j]); 67 } else { 68 if(!l&&!u)upd(G[S],g),upd(G[trans(S,j,1,2)],g+a[i][j]); 69 else if(!l&&u)upd(G[S],g+a[i][j]),upd(G[trans(S,j,u,0)],g+a[i][j]); 70 else if(l&&!u)upd(G[S],g+a[i][j]),upd(G[trans(S,j,0,l)],g+a[i][j]); 71 else if(l==1&&u==1)upd(G[linkll(S,j)],g+a[i][j]); 72 else if(l==2&&u==2)upd(G[linkrr(S,j)],g+a[i][j]); 73 else if(l==2&&u==1)upd(G[trans(S,j,0,0)],g+a[i][j]); 74 } 75 } 76 } 77 return dp[f][0]; 78 } 79 int main() { 80 scanf("%d",&n); 81 m=3; 82 sx=1,sy=3,tx=n,ty=1; 83 for(int j=m; j>=1; --j) 84 for(int i=1; i<=n; ++i) 85 scanf("%d",&a[i][j]); 86 printf("%lld\n",solve()); 87 return 0; 88 }