P3190 [HNOI2007]神奇游乐园

题目

求一个网格图权值和最大的哈密顿回路。

分析

其实和模板题没有太大变化,就是记得要加上贡献和添加时是个比较大小而不是个数求和。

代码

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
	while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
#define ll long long
#define PII pair<int,int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ull unsigned long long
const int N=3e5+5,M=7,K=3e5+5,INF=1e9+7,MOD=299991;
struct state{int a[M];};
int n,m,now,lst,edi,edj;
ll Ans,val[N<<1],to[N<<1],d[N][M];
int head[K],nex[N<<1],idx[2];
struct Node{int nex,to[2];ll val[2];}s[N];
inline void cmax(ll &x,ll y){if(x<y) x=y;}
inline void Insert(int x,ll v){
	int key=x%MOD;
	for(int i=head[key];i;i=s[i].nex) if(s[i].to[now]==x) return cmax(s[i].val[now],v),void();
	s[++idx[now]].nex=head[key];
	s[idx[now]].to[now]=x;
	s[idx[now]].val[now]=v;
	head[key]=idx[now];
	return ;
}
inline state Unpack(ll x){
	state S;S.a[0]=x&3;
	for(ll i=1;i<=m;i++) S.a[i]=((x>>(i<<1))&3);
	return S;
} 
inline ll Judge(state S){
	int res=0;res|=S.a[0];
	for(ll i=1;i<=m;i++) res|=(S.a[i]<<(i<<1));
	return res;
}
char str[M];
bool vis[N][M];
void DP(){
	Insert(0,0);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			lst=now,now^=1;memset(head,0,sizeof(head));idx[now]=0;
			for(int k=1;k<=idx[lst];k++){
				state tmp=Unpack(s[k].to[lst]),las=tmp;
				ll num=s[k].val[lst]+d[i][j];int west=las.a[0],north=las.a[j];
				if(!west&&!north){
					Insert(Judge(las),num-d[i][j]);
					if(vis[i+1][j]&&vis[i][j+1]){
						las.a[0]=2,las.a[j]=1;
						Insert(Judge(las),num);
						las=tmp;
					}
					continue;
				}
				if(!west&&north){
					if(vis[i+1][j]) Insert(Judge(las),num);
					if(vis[i][j+1]){
						las.a[j]=0,las.a[0]=north;
						Insert(Judge(las),num);
						las=tmp;
					}
					continue;
				}
				if(west&&!north){
					if(vis[i][j+1]) Insert(Judge(las),num);
					if(vis[i+1][j]){
						las.a[j]=west,las.a[0]=0;
						Insert(Judge(las),num);
						las=tmp;
					}
					continue;
				}
				if(west==1&&north==1){
					int pos,res=1;
					for(pos=j+1;pos<=m;pos++){
						res+=las.a[pos]==1?1:las.a[pos]==2?-1:0;
						if(res==0) break;
					} 
					las.a[pos]=1,las.a[0]=las.a[j]=0;
					Insert(Judge(las),num);las=tmp;
					continue;
				}
				if(west==2&&north==2){
					int pos,res=-1;
					for(pos=j-1;pos;pos--){
						res+=las.a[pos]==1?1:las.a[pos]==2?-1:0;
						if(res==0) break;
					} 
					las.a[pos]=2,las.a[0]=las.a[j]=0;
					Insert(Judge(las),num);las=tmp;
					continue;
				}
				if(west==2&&north==1){
					las.a[0]=las.a[j]=0;
					Insert(Judge(las),num);
					las=tmp;
					continue;
				}
				if(west==1&&north==2){
					bool fl=0;
					las.a[0]=las.a[j]=0;
					if(!fl) cmax(Ans,num);
					continue;
				}
			}
		}
	}
	return ;
}
signed main(){
	read(n),read(m);Ans=-INF;
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) read(d[i][j]),vis[i][j]=true;
	edi=n,edj=m;
	DP();
	write(Ans);
	return 0;
}
posted @ 2021-07-19 21:28  __Anchor  阅读(27)  评论(0编辑  收藏  举报