zoukankan      html  css  js  c++  java
  • [HNOI2007]神奇游乐园

    题面在这里

    题意

    四通格中每格都有权值(a_{ij}),求单回路上路径权值和的最大值

    数据范围

    [2le nle 100,2le mle 6,-10^3le 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
    ",ans);
    }
    
    int main()
    {
    	init();solve();
    	return 0;
    }
    
    
  • 相关阅读:
    爬取药智网中的方剂信息
    日报3.13
    数据库添加出错
    Bencode
    一些安全网络协议
    代码质量不重要
    Jordan Peterson
    随身记录的缺点
    Why is Go PANICking?
    go问
  • 原文地址:https://www.cnblogs.com/cjfdf/p/8692147.html
Copyright © 2011-2022 走看看