插头DP
sigh……其实思路很简单的= =就多加一种转移:从(0,0)->(0,0),也就是不走这个格子……
初始状态就是第一格有一个左插头= =结束状态可以让(n,m)这个位置可以走到(n+1,m),这样就符合题意了= =
然后一个大坑出现:
转移时不能随意修改sum值!!因为一个状态两次转移的话,第一次修改了sum值,第二次的转移就会出错!!
http://blog.csdn.net/xingyeyongheng/article/details/24499375 我还是看了这篇博客才幡然醒悟!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //BZOJ 3377 2 #include<cmath> 3 #include<vector> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<iostream> 8 #include<algorithm> 9 #define rep(i,n) for(int i=0;i<n;++i) 10 #define F(i,j,n) for(int i=j;i<=n;++i) 11 #define D(i,j,n) for(int i=j;i>=n;--i) 12 #define pb push_back 13 #define CC(a,b) memset(a,b,sizeof(a)) 14 using namespace std; 15 int getint(){ 16 int v=0,sign=1; char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') sign=-1; ch=getchar();} 18 while(isdigit(ch)) {v=v*10+ch-'0'; ch=getchar();} 19 return v*sign; 20 } 21 const int N=1e7+10,INF=~0u>>2; 22 const double eps=1e-8; 23 /*******************template********************/ 24 const int M=100007; 25 typedef long long LL; 26 int mp[12][12]; 27 bool mmp[12][12]; 28 int n,m,k; 29 int tot[2],bit[12],hash[M],state[2][M]; 30 LL dp[2][M],ans; 31 32 void init(){ 33 CC(mp,0); 34 CC(mmp,0); 35 char ch; 36 F(i,1,n) F(j,1,m) {scanf("%d",&mp[i][j]); mmp[i][j]=1;} 37 mmp[n+1][m]=1; 38 F(i,0,1) F(j,0,M-1) dp[i][j]=-INF; 39 tot[0]=1; ans=-INF; 40 k=0; 41 dp[0][1]=mp[1][1]; 42 state[0][1]=1; 43 } 44 void hash_in(int s,LL sum){ 45 int p=s%M; 46 while(hash[p]){ 47 if (state[k][hash[p]]==s){ 48 dp[k][hash[p]]=max(dp[k][hash[p]],sum); 49 return; 50 } 51 p++; 52 if (p==M) p=0; 53 } 54 hash[p]=++tot[k]; 55 state[k][hash[p]]=s; 56 dp[k][hash[p]]=sum; 57 } 58 #define in hash_in(s,sum) 59 void work(){ 60 F(i,1,n){ 61 F(j,1,m){ 62 k^=1; 63 tot[k]=0; 64 CC(hash,0); 65 F(u,1,tot[1-k]){ 66 int s=state[1-k][u]; 67 LL sum=dp[1-k][u]; 68 int p=(s>>bit[j-1])&3,q=(s>>bit[j])&3,d=(s>>bit[j+1])&3; 69 if (!p && !q){ 70 in; 71 if (!mmp[i+1][j] || !mmp[i][j+1]) continue; 72 s=s^(1<<bit[j-1])^(1<<bit[j]<<1); 73 sum=sum+mp[i][j]+mp[i+1][j]; 74 if (!d) sum+=mp[i][j+1]; 75 in; 76 }else if(!p && q){ 77 if (mmp[i][j+1]){ 78 // if (!d) sum+=mp[i][j+1]; 79 if (!d) hash_in(s,sum+mp[i][j+1]); 80 else in; 81 } 82 if (mmp[i+1][j]){ 83 s=s^q*(1<<bit[j])^q*(1<<bit[j-1]); 84 sum+=mp[i+1][j]; in; 85 } 86 }else if(p && !q){ 87 if (mmp[i+1][j]) hash_in(s,sum+mp[i+1][j]); 88 if (mmp[i][j+1]){ 89 s=s^p*(1<<bit[j])^p*(1<<bit[j-1]); 90 if (!d)sum+=mp[i][j+1]; 91 in; 92 } 93 }else if(p+q==2){ 94 int nd=1; 95 F(u,j+1,m){ 96 int w=(s>>bit[u])&3; 97 if (w==1) nd++; 98 if (w==2) nd--; 99 if (!nd){ s-=1<<bit[u]; break; } 100 } 101 s=s^(1<<bit[j-1])^(1<<bit[j]),in; 102 }else if(p+q==4){ 103 int nd=1; 104 D(u,j-2,1){ 105 int w=(s>>bit[u])&3; 106 if (w==2) nd++; 107 if (w==1) nd--; 108 if (!nd){ s+=1<<bit[u]; break; } 109 } 110 s=s^(1<<bit[j-1]<<1)^(1<<bit[j]<<1),in; 111 }else if(p==2 && q==1){ 112 s=s^(1<<bit[j-1]<<1)^(1<<bit[j]),in; 113 }else if(p==1 && q==2) continue; 114 } 115 } 116 F(j,1,tot[k]) state[k][j]<<=2; 117 } 118 F(i,1,tot[k]) ans=max(ans,dp[k][i]); 119 } 120 int main(){ 121 #ifndef ONLINE_JUDGE 122 freopen("3377.in","r",stdin); 123 // freopen("output.txt","w",stdout); 124 #endif 125 F(i,0,10) bit[i]=i<<1; 126 int T=0; 127 while(scanf("%d%d",&n,&m)!=EOF){ 128 init(); 129 work(); 130 printf("Case %d: %lld ",++T,ans); 131 } 132 return 0; 133 }