1. 程式人生 > >[HNOI2007]神奇遊樂園

[HNOI2007]神奇遊樂園

-m ems mar ios else out init pre inline

題面在這裏

題意

四通格中每格都有權值\(a_{ij}\),求單回路上路徑權值和的最大值

數據範圍

\[2\le n\le 100,2\le m\le 6,-10^3\le a_{ij}\le10^3\]

sol

插頭DP,最後合並單回路的時候就不要記狀態了,直接更新答案就好

代碼

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector> #include<cstdio> #include<string> #include<bitset> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define mp make_pair #define pub push_back #define puf push_front #define pob pop_back #define pof pop_front
#define RG register #define il inline using namespace std; typedef unsigned long long ull; typedef vector<int>VI; typedef long long ll; typedef double dd; const dd eps=1e-10; const int mod=1e8; const int N=1000010; const int inf=2147483647; il ll read(){ RG ll data=0,w=1;RG char ch=getchar(); while
(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar(); if(ch==‘-‘)w=-1,ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘)data=data*10+ch-48,ch=getchar(); return data*w; } il void file(){ freopen("a.in","r",stdin); freopen("a.out","w",stdout); } int n,m,mz[105][8],ans=-inf; map<int,int>M[2]; map<int,int>::iterator tmp; il void print(int x){putchar(48+(x&3));if(x>>2)print(x>>2);} il void init(){ n=read();m=read(); memset(mz,129,sizeof(mz)); for(RG int i=1;i<=n;i++) for(RG int j=1;j<=m;j++) mz[i][j]=read(); } int p1,p2,p3,q1,q2,q3,k,d,pos,cal; il void dpblank(int i,int j,int cur){ p1=1<<(2*(j-1));q1=1<<(2*j); p2=2<<(2*(j-1));q2=2<<(2*j); p3=3<<(2*(j-1));q3=3<<(2*j); for(tmp=M[cur^1].begin();tmp!=M[cur^1].end();tmp++){ k=tmp->first;d=tmp->second+mz[i][j];cal=0; if(!(k&p3)&&!(k&q3)&&i+1<=n&&j+1<=m){//新建,## k=k|p1|q2; if(M[cur].find(k)==M[cur].end())M[cur][k]=d; else M[cur][k]=max(M[cur][k],d); } else if((k&p2)&&(k&q1)){//合並,)( k=k^p2^q1; if(M[cur].find(k)==M[cur].end())M[cur][k]=d; else M[cur][k]=max(M[cur][k],d); } else if((k&p1)&&(k&q2)&&!(k^p1^q2)){//合並,() ans=max(ans,d);//直接統計答案 } else if((k&p2)&&(k&q2)){//合並,)) for(pos=2*(j-2);cal||((k>>pos)&3)!=1;pos-=2) if(((k>>pos)&3)==2)cal++; else if(((k>>pos)&3)==1)cal--; k=k^p2^q2^(3<<pos);if(j==m)k<<=2; if(M[cur].find(k)==M[cur].end())M[cur][k]=d; else M[cur][k]=max(M[cur][k],d); } else if((k&p1)&&(k&q1)){//合並,(( for(pos=2*(j+1);cal||((k>>pos)&3)!=2;pos+=2) if(((k>>pos)&3)==1)cal++; else if(((k>>pos)&3)==2)cal--; k=k^p1^q1^(3<<pos); if(M[cur].find(k)==M[cur].end())M[cur][k]=d; else M[cur][k]=max(M[cur][k],d); } else if((k&p3)&&!(k&q3)){//保持, )# / (# if(i!=n){//下 if(j==m)k<<=2; if(M[cur].find(k)==M[cur].end())M[cur][k]=d; else M[cur][k]=max(M[cur][k],d); } if(j!=m){//右 k=k^(k&p3)|((k&p3)<<2); if(M[cur].find(k)==M[cur].end())M[cur][k]=d; else M[cur][k]=max(M[cur][k],d); } } else if(!(k&p3)&&(k&q3)){//保持, #) / #( if(j!=m){//右 if(M[cur].find(k)==M[cur].end())M[cur][k]=d; else M[cur][k]=max(M[cur][k],d); } if(i!=n){//下 k=k^(k&q3)|((k&q3)>>2);if(j==m)k<<=2; if(M[cur].find(k)==M[cur].end())M[cur][k]=d; else M[cur][k]=max(M[cur][k],d); } } } } il void dpblock(int i,int j,int cur){ p3=3<<(2*(j-1));q3=3<<(2*j); for(tmp=M[cur^1].begin();tmp!=M[cur^1].end();tmp++){ k=tmp->first;d=tmp->second; if(!(k&p3)&&!(k&q3)){ if(j==m)k<<=2; if(M[cur].find(k)==M[cur].end())M[cur][k]=d; else M[cur][k]=max(M[cur][k],d); } } } il void solve(){ M[0][0]=0;RG int cur=0; for(RG int i=1;i<=n;i++) for(RG int j=1;j<=m;j++) M[cur^=1].clear(),dpblank(i,j,cur),dpblock(i,j,cur); printf("%d\n",ans); } int main() { init();solve(); return 0; }

[HNOI2007]神奇遊樂園