2019.02.18【HDU1693】Eat the Trees(轮廓线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;
	
	Map(){memset(key,-1,sizeof key);}
	
	struct iterator{
		int now;
		Map* belong;
		iterator(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 now!=b.now||belong!=b.belong;
		}
	};
	
	iterator begin(){return iterator(this,1);}
	iterator end(){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){
			sta[++top]=h;
			key[h]=k;
		}
		return val[h];
	}
	
	void clear(){
		while(top){
			key[sta[top]]=-1;
			val[sta[top]]=0;
			--top;
		}
	}
}ma[2];

int n,m,nn,mm,pre;
bool ok[14][14];

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

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

inline int set_state(int s,int j,int bj,int bn){
	return (s&~(3<<j))|((bj|(bn<<1))<<j);
}

inline void dp(){
	if(nn==-1){
		ma[pre][0]=0;
		return ;
	}
	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<<=1;
			int sl=get_state(s,j),su=get_state(s,j+1);
			if(!ok[i][j]){
				if(!(sl|su))ma[now][set_state(s,j,0,0)]+=nowans;
			}
			else if(!sl&&!su){
				if(ok[i][j+1]&&ok[i+1][j])ma[now][set_state(s,j,1,1)]+=nowans;
			}
			else if(!sl||!su){
				if(ok[i][j+1])ma[now][set_state(s,j,0,1)]+=nowans;
				if(ok[i+1][j])ma[now][set_state(s,j,1,0)]+=nowans;
			}
			else {
				ma[now][set_state(s,j,0,0)]+=nowans;
			}
		}
		pre=now;
	}
}

inline void solve(int id){
	nn=-1;
	scanf("%d%d",&n,&m);
	for(int re i=0,x;i<n;++i)
	for(int re j=0;j<m;++j){
		scanf("%d",&x);
		ok[i][j]=x;
		if(x)nn=i,mm=j;
	}
	dp();
	cout<<"Case "<<id<<": There are "<<ma[pre][0]<<" ways to eat the trees.\n";
}

int T,t;
signed main(){
	for(scanf("%d",&T);T--;solve(++t));
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值