zoukankan      html  css  js  c++  java
  • [URAL1519]Formula 1

    题面在这里

    题意

    四通格内有部分格子为障碍物,求用一个回路将非障碍物格子全部覆盖的方案数

    数据范围

    [2le n,mle 12 ]

    sol

    本蒟蒻插头DP第二题
    入门首推CDQ大佬论文《基于连通性状态压缩的动态规划问题》

    这里我们发现仅仅记录插头是否出现是不行的,
    还需要记录某个插头是否和另一个插头属于同一个回路;
    可以发现两个回路是不会交叉的,这里我们想到括号序列(好像有点快...逃
    于是我们只要记录(#,(,))三种状态,那么就可以解出所有插头的联系问题
    之后讨论即可

    代码

    //4base下的括号序列表示法
    #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 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;
    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,nn,mm,mp[20][20];
    map<int,ll>M[2];
    map<int,ll>::iterator tmp;
    il void print(ll x){putchar(48+(x&3));if(x>>2)print(x>>2);}
    il void init(){
    	char c;nn=mm=0;
    	memset(mp,0,sizeof(mp));
    	for(RG int i=1;i<=n;i++)
    		for(RG int j=1;j<=m;j++){
    			c=0;while(c!='*'&&c!='.')c=getchar();
    			mp[i][j]=(c=='.');if(mp[i][j])nn=i,mm=j;
    		}
    }
    
    il void dpblank(int i,int j,bool cur){
    	RG int p1,q1,p2,q2,p3,q3,k,w,cal,pos;
    	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].begin();tmp!=M[cur].end();tmp++){
    		k=w=tmp->first;cal=0;
    		if((k&p3)==0&&(k&q3)==0&&mp[i+1][j]&&mp[i][j+1]){
    			w=k|p1|q2;if(j==m)w<<=2;
    			M[cur^1][w]+=M[cur][k];
    		}
    		else if((k&p3)==p2&&(k&q3)==q1){//合并,)(
    			w=k^p2^q1;if(j==m)w<<=2;
    			M[cur^1][w]+=M[cur][k];
    		}
    		else if((k&p3)==p2&&(k&q3)==q2){//合并,))
    			for(pos=2*(j-2);!(cal==0&&((k>>pos)&3)==1);pos-=2)
    				if(((k>>pos)&3)==2)cal++;//2,入栈
    				else if(((k>>pos)&3)==1)cal--;//1,出栈
    			w=k^p2^q2^(3<<pos);if(j==m)w<<=2;
    			M[cur^1][w]+=M[cur][k];
    		}
    		else if((k&p3)==p1&&(k&q3)==q1){//合并,((
    			for(pos=2*(j+1);!(cal==0&&((k>>pos)&3)==2);pos+=2)
    				if(((k>>pos)&3)==1)cal++;//1,入栈
    				else if(((k>>pos)&3)==2)cal--;//2,出栈
    			w=k^p1^q1^(3<<pos);if(j==m)w<<=2;
    			M[cur^1][w]+=M[cur][k];
    		}
    		else if((k&p3)==p1&&(k&q3)==q2&&i==nn&&j==mm){//合并,()
    			w=0;
    			M[cur^1][w]+=M[cur][k];
    		}
    		else if((k&p3)&&!(k&q3)){//保持,(#
    			if(mp[i+1][j]){
    				w=k;if(j==m)w<<=2;
    				M[cur^1][w]+=M[cur][k];
    			}
    			if(mp[i][j+1]){
    				w=k^(k&p3)|((k&p3)<<2);
    				M[cur^1][w]+=M[cur][k];
    			}
    		}
    		else if((k&q3)&&!(k&p3)){//保持,#(
    			if(mp[i+1][j]){
    				w=k^(k&q3)|((k&q3)>>2);if(j==m)w<<=2;
    				M[cur^1][w]+=M[cur][k];
    			}
    			if(mp[i][j+1]){
    				w=k;
    				M[cur^1][w]+=M[cur][k];
    			}		
    		}
    	}
    }
    
    il void dpblock(int i,int j,bool cur){
    	RG int k,w;
    	for(tmp=M[cur].begin();tmp!=M[cur].end();tmp++){
    		w=k=tmp->first;if(j==m)w<<=2;
    		M[cur^1][w]+=M[cur][k];
    	}	
    }
    
    il void solve(){
    	RG bool cur=0;
    	M[0].clear();M[0][0]=1;cur^=1;
    	for(RG int i=1;i<=n;i++)
    		for(RG int j=1;j<=m;j++){
    			M[cur].clear();
    			if(mp[i][j])dpblank(i,j,cur^1);
    			else dpblock(i,j,cur^1);
    			cur^=1;
    		}
    	cur^=1;
    	if(M[cur].size()&&M[cur].begin()->first==0)
    		printf("%lld
    ",M[cur].begin()->second);
    	else puts("0");
    }
    
    int main()
    {
    	while(scanf("%d%d",&n,&m)==2){
    		init();solve();
    	}
    	return 0;
    }
    

    其实这份代码应该可以压一压行的

  • 相关阅读:
    react Table key值使用方式
    C# EF查询不同分组的第一条数据
    C# MVC PDFJS URL传参方式+文件流方式在线展示文档
    docker nginx配置写错,启动不了容器的解决方案
    网络编程之BIO和NIO
    网络编程之BIO和NIO
    IT职场心得感想
    我们希望能与各位快乐拼博的站长们一路前行
    UART, SPI详解
    创业精神
  • 原文地址:https://www.cnblogs.com/cjfdf/p/8690081.html
Copyright © 2011-2022 走看看