http://www.lydsy.com/JudgeOnline/problem.php?id=1187 (题目链接)
题意
一个$n*m$的矩阵,其中每一个位置有一个权值,求一条回路使得经过的位置的权值和最大。
Solution
插头dp,插头维护连通信息,更新答案的条件就是合并的左插头和右插头属于同一连通块,且当前状态已经没有其它插头了。更新完答案后这个状态不会再被记入下一次dp。
代码
// bzoj1185 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define HAS 6311 #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxd=10,maxs=100010,maxh=6400; int code[maxd],cnts[maxd],n,m; int head[maxh],next[maxs]; int size[2],tot[2][maxs],s[2][maxs]; void decode(int st) { for (int i=m;i>=0;i--) code[i]=st&7,st>>=3; } int encode() { int st=0,cnt=0; memset(cnts,-1,sizeof(cnts));cnts[0]=0; for (int i=0;i<=m;i++) { if (cnts[code[i]]==-1) cnts[code[i]]=++cnt; code[i]=cnts[code[i]]; } for (int i=0;i<=m;i++) st=st<<3|code[i]; return st; } void shift() { for (int i=m;i;i--) code[i]=code[i-1];code[0]=0; } void add(int p,int num) { int st=encode(); int id=st%HAS; for (int i=head[id];i;i=next[i]) if (s[p][i]==st) {tot[p][i]=max(tot[p][i],num);return;} s[p][++size[p]]=st;tot[p][size[p]]=num; next[size[p]]=head[id];head[id]=size[p]; } int main() { scanf("%d%d",&n,&m); int p=0,ans=-inf,val; size[0]=1;tot[0][1]=0;s[0][1]=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { scanf("%d",&val); size[p^=1]=0; memset(head,0,sizeof(head)); for (int k=1;k<=size[p^1];k++) { decode(s[p^1][k]); int left=code[j-1],up=code[j]; if (left && up) { if (left==up) { int flag=0; for (int l=0;l<j-1;l++) if (code[l]) {flag=1;break;} for (int l=j+1;l<=m;l++) if (code[l]) {flag=1;break;} if (!flag) ans=max(ans,tot[p^1][k]+val); } else { code[j-1]=code[j]=0; for (int l=0;l<=m;l++) if (code[l]==up) code[l]=left; if (j==m) shift(); add(p,tot[p^1][k]+val); } } else if (left || up) { int tmp=left ? left : up; if (j<m) { code[j-1]=0,code[j]=tmp; add(p,tot[p^1][k]+val); } if (i<n) { code[j-1]=tmp,code[j]=0; if (j==m) shift(); add(p,tot[p^1][k]+val); } } else { if (i<n && j<m) { code[j-1]=code[j]=8; add(p,tot[p^1][k]+val); } code[j-1]=code[j]=0; if (j==m) shift(); add(p,tot[p^1][k]); } } } printf("%d",ans); return 0; }