2019.02.19【URAL1519】Formula 1(轮廓线DP)

传送门


补档计划,无题解。


代码(括号序列):

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define cs const

struct Map{
    static cs int magic=189859;
    int key[magic];
	ll val[magic];
    int sta[magic],top;
    
    struct iterator{
        int now;
        cs Map *belong;
        iterator(cs Map *a,cs int &_now):belong(a),now(_now){}
        int key(){return belong->key[belong->sta[now]];}
        ll val(){return belong->val[belong->sta[now]];}
        iterator operator++(){
            ++now;
            return *this;
        }
        bool operator!=(cs iterator &b)cs{
            return belong!=b.belong||now!=b.now;
        }
    };
    
    Map(){memset(key,-1,sizeof key);}
    
    iterator begin()cs{return iterator(this,1);}
    iterator end()cs{return iterator(this,top+1);}
    
    cs ll &operator[](cs int &k)cs{
        int h=k%magic;
        while((~key[h])&&(key[h]^k))h=(h+1)%magic;
        return val[h];
    }
    ll &operator[](cs int &k){
        int h=k%magic;
        while((~key[h])&&(key[h]^k))h=(h+1)%magic;
        if(key[h]^k){
            key[h]=k;
            sta[++top]=h;
        }
        return val[h];
    }
    void clear(){
        while(top){
            key[sta[top]]=-1;
            val[sta[top]]=0;
            --top;
        }
    }
}ma[2];

int n,m,nn=-1,mm,pre=0;
bool ok[15][15];
int bits[15];

inline int get_state(int s,int j){
	return (s&bits[j])>>(j<<1);
}

inline int set_state(int s,int j,int b){
	return (s&~bits[j])|(b<<(j<<1));
}

inline int set_state(int s,int j,int bj,int bn){
	return (s&~(bits[j]|bits[j+1]))|((bj|(bn<<2))<<(j<<1));
}

inline int find_match(int s,int j){
	int c=get_state(s,j),d=c==1?1:-1,f=0;
	for(;;j+=d){
        if(get_state(s,j)==c)f++;
        else if(get_state(s,j))f--;
        if(f==0) return j;
    }
}

inline void dp(){
	ma[0].clear();ma[1].clear();pre=0;
	ma[pre][0]=1;
	for(int re i=0;i<n;++i)
	for(int re j=0;j<m;++j){
		int now=pre^1;
		ma[now].clear();
		for(Map::iterator it=ma[pre].begin();it!=ma[pre].end();++it){
			int s=it.key();
			ll nowans=it.val();
			if(j==0)s<<=2; 
			int sl=get_state(s,j),su=get_state(s,j+1);
			if(!sl&&!su){
				if(!ok[i][j])ma[now][set_state(s,j,0,0)]+=nowans;
				else if(ok[i][j+1]&&ok[i+1][j])ma[now][set_state(s,j,1,2)]+=nowans;
			}
			else if(!sl||!su){
				if(ok[i][j+1])ma[now][set_state(s,j,0,sl|su)]+=nowans;
				if(ok[i+1][j])ma[now][set_state(s,j,sl|su,0)]+=nowans;
			}
			else if(sl==su){
				int posl=find_match(s,j),posu=find_match(s,j+1);
				int mn=min(posl,posu),mx=max(posl,posu);
				int bs=set_state(s,mn,1);
				bs=set_state(bs,mx,2);
				ma[now][set_state(bs,j,0,0)]+=nowans;
			}
			else if(sl==2&&su==1)ma[now][set_state(s,j,0,0)]+=nowans;
			else if(i==nn&&j==mm)ma[now][set_state(s,j,0,0)]+=nowans;
		}
		pre=now;
	}
}

char s[20];
signed main(){
	cin>>n>>m;
	for(int re i=0;i<n;++i){
		scanf("%s",s);
		for(int re j=0;j<m;++j){
			if(s[j]=='.')ok[i][j]=1,nn=i,mm=j;
		}
	}
	for(int re i=0;i<=m;++i)bits[i]=3<<(i<<1);
	dp();
	cout<<ma[pre][0]<<"\n";
	return 0;
}

代码(最小表示法):

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define cs const

int n,m,nn=-1,mm,pre=0;
bool ok[15][15];
int mk[8];

struct Map{
	static cs int magic=189859;
	ll key[magic],val[magic];
	int sta[magic],top;
	
	struct iterator{
		int now;
		cs Map *belong;
		iterator(cs Map *a,cs int &_now):belong(a),now(_now){}
		ll key(){return belong->key[belong->sta[now]];}
		ll val(){return belong->val[belong->sta[now]];}
		iterator operator++(){
			++now;
			return *this;
		}
		bool operator!=(cs iterator &b)cs{
			return belong!=b.belong||now!=b.now;
		}
	};

	Map(){memset(key,-1,sizeof key);}

	iterator begin()cs{return iterator(this,1);}
	iterator end()cs{return iterator(this,top+1);}

	cs ll &operator[](cs ll &k)cs{
		int h=k%magic;
		while((~key[h])&&(key[h]^k))h=(h+1)%magic;
		return val[h];
	}
	ll &operator[](cs ll &k){
		int h=k%magic;
		while((~key[h])&&(key[h]^k))h=(h+1)%magic;
		if(key[h]^k){
			key[h]=k;
			sta[++top]=h;
		}
		return val[h];
	}
	void clear(){
		while(top){
			key[sta[top]]=-1;
			val[sta[top]]=0;
			--top;
		}
	}
}ma[2];
ll mask_one=07;

int get_state(cs ll &st,cs int &i){
	return (st&(mask_one<<i*3))>>i*3;
}

void set_state(ll &s,int i,ll ns){
	s&=~(mask_one<<3*i);
	s|=ns<<3*i;
}

void set_state(ll &st,int i,ll sj,ll su){
	set_state(st,i,sj);
	set_state(st,i+1,su);
}

ll rearrange(ll s){
	memset(mk,-1,sizeof mk);
	mk[0]=0;
	int cnt=1;
	for(int re i=0;i<=m;++i){
		int st=get_state(s,i);
		if(mk[st]==-1)mk[st]=cnt++;
	}
	for(int re i=0;i<=m;++i){
		int st=get_state(s,i);
		if(mk[st]!=st)set_state(s,i,mk[st]);
	}
	return s;
}

void dp(){
	ma[0].clear();ma[1].clear();pre=0;
	ma[pre][0]=1;
	for(int re i=0;i<n;++i)
	for(int re j=0;j<m;++j){
		bool now=pre^1;
		ma[now].clear();
		for(Map::iterator it=ma[pre].begin();it!=ma[pre].end();++it){
			ll s=it.key(),nowans=it.val();
			if(j==0)s<<=3;
			int su=get_state(s,j+1),sl=get_state(s,j);
			if(!su&&!sl){
				if(!ok[i][j]){
					set_state(s,j,0,0);
					ma[now][s]+=nowans;
				}
				else if(ok[i][j+1]&&ok[i+1][j]){
					set_state(s,j,7,7);
					ma[now][rearrange(s)]+=nowans;
				}
			}
			else if(!sl||!su){
				if(ok[i][j+1]){
					set_state(s,j,0,su+sl);
					ma[now][s]+=nowans;
				}
				if(ok[i+1][j]){
					set_state(s,j,su+sl,0);
					ma[now][s]+=nowans;
				}
			}
			else if(su^sl){
				int nb=min(su,sl),mb=max(su,sl);
				set_state(s,j,0,0);
				for(int re k=0;k<m+1;++k){
					int st=get_state(s,k);
					if(st==sl||st==su)set_state(s,k,nb);
					else if(st>mb)set_state(s,k,st-1);
				}
				ma[now][s]+=nowans;
			}
			else if(i==nn&&j==mm){
				set_state(s,j,0,0);
				ma[now][s]+=nowans;
			}
		}
		pre=now;
	}
}

char s[20];
signed main(){
    scanf("%d%d",&n,&m);
    for(int re i=0;i<n;++i){
        scanf("%s",s);
        for(int re j=0;j<m;++j){
            if(s[j]=='.'){
                ok[i][j]=true;
                nn=i,mm=j;
            }
        }
    }
    dp();
    cout<<ma[pre][0];
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值