[HNOI2007][bzoj1187] 神奇游乐园 [插头dp]
题面:
给定一个四联通棋盘图,每个格子有权值,求一条总权值最大的回路
思路:
棋盘?
回路?
n,m<=10?
当然是插头dp啦~\(≧▽≦)/~
然后发现这道题并不是哈密顿回路了......需要考虑一下终止条件的不同,对比URAL1519
诚然,回路问题中依然可以用括号表示法来压缩状态,但是此时形成回路、统计答案的就不仅仅在最后一个非障碍格子才可以,而是任何时候,只要状态中只剩下一对左右插头满足条件(看不懂这里的可以去上面那道题看看)
同时请注意,这道题统计的是最值、不是和值
同时请注意,这题可能会爆longlong......我丧病地开了__int128,避免了高精度的地狱
Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 #define hash deep_dark_fantasy 7 #define inf 1e9 8 using namespace std; 9 inline int read(){ 10 int re=0,flag=1;char ch=getchar(); 11 while(ch>'9'||ch<'0'){ 12 if(ch=='-') flag=-1; 13 ch=getchar(); 14 } 15 while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar(); 16 return re*flag; 17 } 18 int n,m,x[150][150],cur,pre,ex,ey; 19 int st[2][300010];ll ans[2][300010],re; 20 int tot[2],bit[20],state[300010],st_tot,hash=300000; 21 struct edge{ 22 int to,next; 23 }a[300010]; 24 void insert(int sta,ll val){ 25 int p=sta%hash,i; 26 for(i=state[p];i;i=a[i].next){ 27 if(st[cur][a[i].to]==sta){ 28 ans[cur][a[i].to]=max(ans[cur][a[i].to],val);return; 29 } 30 } 31 tot[cur]++; 32 a[++st_tot].to=tot[cur]; 33 a[st_tot].next=state[p]; 34 state[p]=st_tot;st[cur][tot[cur]]=sta;ans[cur][tot[cur]]=val; 35 } 36 void dp(){ 37 int i,j,k,l,now,down,right;ll val;re=-inf; 38 cur=0;tot[cur]=1;ans[cur][1]=0;st[cur][1]=0; 39 for(i=1;i<=n;i++){ 40 for(j=1;j<=tot[cur];j++) st[cur][j]<<=2; 41 for(j=1;j<=m;j++){ 42 pre=cur;cur^=1;tot[cur]=0;st_tot=0;memset(state,0,sizeof(state)); 43 for(k=1;k<=tot[pre];k++){ 44 now=st[pre][k];val=ans[pre][k]; 45 right=(now>>bit[j-1])%4;down=(now>>bit[j])%4; 46 if(!down&&!right){ 47 insert(now,val); 48 if(j!=m) 49 insert(now+(1<<bit[j-1])+((1<<bit[j])<<1),val+x[i][j]); 50 } 51 if(down&&!right){ 52 insert(now-down*(1<<bit[j])+down*(1<<bit[j-1]),val+x[i][j]); 53 if(j!=m)insert(now,val+x[i][j]); 54 } 55 if(right&&!down){ 56 insert(now,val+x[i][j]); 57 if(j!=m) 58 insert(now+right*(1<<bit[j])-right*(1<<bit[j-1]),val+x[i][j]); 59 } 60 if(right==1&&down==1){ 61 int cnt=1; 62 for(l=j+1;l<=m;l++){ 63 if((now>>bit[l])%4==1) cnt++; 64 if((now>>bit[l])%4==2) cnt--; 65 if(!cnt){ 66 insert(now-(1<<bit[l])-(1<<bit[j])-(1<<bit[j-1]),val+x[i][j]); 67 break; 68 } 69 } 70 } 71 if(right==2&&down==2){ 72 int cnt=1; 73 for(l=j-2;l>=0;l--){ 74 if((now>>bit[l])%4==1) cnt--; 75 if((now>>bit[l])%4==2) cnt++; 76 if(!cnt){ 77 insert(now+(1<<bit[l])-((1<<bit[j])<<1)-((1<<bit[j-1])<<1),val+x[i][j]); 78 break; 79 } 80 } 81 } 82 if(right==2&&down==1){ 83 insert(now-((1<<bit[j-1])<<1)-(1<<bit[j]),val+x[i][j]); 84 } 85 if(right==1&&down==2){ 86 if((now==(1<<bit[j-1])+((1<<bit[j])<<1))&&(val+x[i][j]>re)){ 87 re=val+x[i][j]; 88 } 89 } 90 } 91 } 92 } 93 } 94 int main(){ 95 int i,j; 96 n=read();m=read(); 97 for(i=1;i<=10;i++) bit[i]=(i<<1); 98 for(i=1;i<=n;i++) for(j=1;j<=m;j++) x[i][j]=read(); 99 dp(); 100 printf("%lld",re); 101 }