2019.02.26【九省联考2018】【BZOJ5248】【洛谷P4363】双木棋(状压DP)(记忆化搜索)

BZOJ传送门

洛谷传送门


解析:

我们发现当前可决策格子是有限的,实际上,总的状态数非常少,只有9e4种左右,所以我们可以用一个longlong来压一下每一列当前已经决策了多少个格子,然后用哈希表记忆化搜索一下就行了。


代码:

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

struct Map{
	static cs int magic=3721303;
	ll key[magic];
	int val[magic];
	Map(){memset(key,-1,sizeof key);}
	
	cs int &operator[](cs ll &k)cs{
		int h=k%magic;
		while((~key[h])&&(key[h]^k))h=(h+1)%magic;
		return val[h];
	}
	
	int &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;
		return val[h];
	}
	
	bool find(cs ll &k){
		int h=k%magic;
		while((~key[h])&&(key[h]^k))h=(h+1)%magic;
		return key[h]==k;
	}
}ma;

cs int INF=0x3f3f3f3f;
int a[11][11],b[11][11];
int n,m;
ll mask_one=15;

inline int get_state(ll sta,int pos){
	return (sta&(mask_one<<(pos<<2)))>>(pos<<2);
}

inline ll set_state(ll sta,int pos,ll j){
	return (sta&~(mask_one<<(pos<<2)))|(j<<(pos<<2));
}

inline int dfs(ll sta,bool who){
	if(ma.find(sta))return ma[sta];
	int res=who?-INF:INF;
	for(int re i=1;i<=m;++i){
		int pre=get_state(sta,i-1),now=get_state(sta,i);
		if((i==1||now<pre)&&now<n){
			res=who?
				max(res,dfs(set_state(sta,i,now+1),who^1)+a[now+1][i]):
				min(res,dfs(set_state(sta,i,now+1),who^1)-b[now+1][i]);
			
		}
	}
	return ma[sta]=res;
}

signed main(){
	scanf("%d%d",&n,&m);
	for(int re i=1;i<=n;++i)for(int re j=1;j<=m;++j)scanf("%d",&a[i][j]);
	for(int re i=1;i<=n;++i)for(int re j=1;j<=m;++j)scanf("%d",&b[i][j]);
	ll s=0;for(int re i=1;i<=m;++i)s=set_state(s,i,n);
	ma[s]=0;
	cout<<dfs(0,1);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值