• 插头DP


    神仙的博客

    ( t notice:)

    只有右插头和左插头可以合并,左插头和右插头只可以合并一次

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int N=12;
    const int M=1595323;
    const int mod=500009;
    int n,m,mp[N+5][N+5];
    int p3[N+5],now=0,ex,ey;
    ll ans;
    int ch(char x){return x=='*'||x=='.';}
    struct Hash
    {
    	int mak[M],E;
    	ll dp[M];
    	int h[mod],nxt[M];
    	void clear()
    	{
    		for(int i=0;i<mod;i++) h[i]=0;
    		E=0;
    		return;
    	}
    	void add(int pos,ll d)
    	{
    		int g=pos%mod;
    		for(int i=h[g];i;i=nxt[i])
    		{
    			if(mak[i]==pos)
    			{
    				dp[i]+=d;
    				return;
    			}
    		}
    		E++;
    		mak[E]=pos;
    		dp[E]=d;
    		nxt[E]=h[g];
    		h[g]=E;
    		return;
    	}	
    }D[2];
    int get(int pos,int x)
    {
    	pos/=p3[x];
    	return pos%3;
    }
    void cha(int &pos,int x,int t)
    {
    	int b=get(pos,x);
    	pos-=p3[x]*b;
    	pos+=p3[x]*t;
    	return;
    }
    void tcol()
    {
    	D[now].clear();
    	for(int i=1;i<=D[now^1].E;i++)
    	{
    		int mas=D[now^1].mak[i];
    		ll dp=D[now^1].dp[i];
    		int b=get(mas,m);
    		if(!b) D[now].add(mas*3,dp);
    	}
    	return;
    }
    void up1(int x,int y)
    {
    	D[now].clear();
    	for(int i=1;i<=D[now^1].E;i++)
    	{
    		int mas=D[now^1].mak[i];
    		ll dp=D[now^1].dp[i];
    		int b1=get(mas,y-1),b2=get(mas,y);
    		if(!b1&&!b2) D[now].add(mas,dp);
    	}
    	return;
    }
    int f1(int mas,int x)
    {
    	vector<int> s;
    	for(int i=0;i<=m;i++)
    	{
    		s.push_back(mas%3);
    		mas/=3;
    	}
    	int d=0;
    	for(int i=x;i<=m;i++) 
    	{
    		if(s[i]==1) d++;
    		if(s[i]==2) d--;
    		if(d==0) return i;
    	}
    	return -1;
    }
    int f2(int mas,int x)
    {
    	vector<int> s;
    	for(int i=0;i<=m;i++)
    	{
    		s.push_back(mas%3);
    		mas/=3;
    	}
    	int d=0;
    	for(int i=x;i>=0;i--) 
    	{
    		if(s[i]==1) d++;
    		if(s[i]==2) d--;
    		if(d==0) return i;
    	}
    	return -1;
    }
    void up2(int x,int y)
    {
    	D[now].clear();
    	for(int i=1;i<=D[now^1].E;i++)
    	{
    		int mas=D[now^1].mak[i];
    		ll dp=D[now^1].dp[i];
    		int b1=get(mas,y-1),b2=get(mas,y);
    		if(!b1&&!b2) 
    		{
    			cha(mas,y-1,1);
    			cha(mas,y,2);
    			D[now].add(mas,dp);
    		}
    		else if(!b1&&b2)
    		{
    			D[now].add(mas,dp);
    			cha(mas,y,0);
    			cha(mas,y-1,b2);
    			D[now].add(mas,dp);
    		}
    		else if(b1&&!b2)
    		{
    			D[now].add(mas,dp);
    			cha(mas,y-1,0);
    			cha(mas,y,b1);
    			D[now].add(mas,dp);
    		}
    		else if(b1==b2)
    		{
    			if(b1==1&&b2==1) 
    			{
    				int d1=f1(mas,y);
    				cha(mas,y-1,0);
    				cha(mas,y,0);
    				cha(mas,d1,1);
    				D[now].add(mas,dp);
    			}
    			else
    			{
    				int d2=f2(mas,y-1);
    				cha(mas,y-1,0);
    				cha(mas,y,0);
    				cha(mas,d2,2);
    				D[now].add(mas,dp);				
    			}
    		}
    		else if(b1==2&&b2==1)
    		{
    			cha(mas,y-1,0);
    			cha(mas,y,0);
    			D[now].add(mas,dp);
    		}			
    		else if(x==ex&&y==ey)
    		{
    			cha(mas,y-1,0),cha(mas,y,0);
    			if(mas==0) ans+=dp;
    		}
    	}
    	return;
    }
    int main()
    {
    	p3[0]=1;
    	for(int i=1;i<=N+1;i++) p3[i]=p3[i-1]*3;
    	scanf("%d%d",&n,&m);
    	char w;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			while(!ch(w=getchar()));
    			mp[i][j]=w=='*'?1:0;
    			if(!mp[i][j]) ex=i,ey=j;
    		}
    	}
    	D[0].add(0,1);
    	for(int i=1;i<=n;i++)
    	{
    		now^=1;
    		tcol();
    		for(int j=1;j<=m;j++)
    		{
    			now^=1;
    			if(mp[i][j]) up1(i,j);
    			else up2(i,j);
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    RDD的五个属性
    惰性求值的概念
    大数据shuffle的理解
    简单说明hadoop和hbase的异同
    Linux 下命令有哪几种可使用的通配符?分别代表什么含义?
    linux命令知识点复习
    >/dev/null 2>&1
    JAVA内存泄漏和内存溢出的区别和联系
    Linux各个目录的作用
    JVM标准参数-server与-client参数的区别
  • 原文地址:https://www.cnblogs.com/SegmentTree/p/13052821.html
Copyright © 2020-2023  润新知