zoukankan      html  css  js  c++  java
  • 【bzoj1187】 HNOI2007—神奇游乐园

    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;
    }
    
  • 相关阅读:
    LC 216. Combination Sum III
    基本数据类型及其包装类(二)
    基本数据类型及其包装类(一)
    访问权限控制
    关于类的对象创建与初始化
    垃圾收集机制与内存分配策略
    虚拟机字节码执行引擎
    虚拟机类加载机制
    字节码文件的内部结构之谜
    数值信息的机器级存储
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6420407.html
Copyright © 2011-2022 走看看