[BZOJ5248][记忆化搜索][hash]九省联考:一双木棋

BZOJ5248

典型的 m i n − m a x min-max minmax搜索,状态有点多,需要记忆化
搜索的状态都是一个阶梯形的,可以 h a s h hash hash压起来
m i n − m a x min-max minmax搜索,也称对抗搜索,常见于博弈类问题,即最后得分为 s c o r e A − s c o r e B scoreA-scoreB scoreAscoreB
A A A想让 s c o r e A − s c o r e B scoreA-scoreB scoreAscoreB极大, B B B想让 s c o r e A − s c o r e B scoreA-scoreB scoreAscoreB极小,那么只需要看看搜索到当前状态该谁下就可以判断取 m i n min min还是取 m a x max max

Code:

#include<bits/stdc++.h>
#define INF 1000000000
#define ll long long
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=15;
ll lim;
int n,m;
int a[N][N],b[N][N];
int pt[N];
map<ll,int>mp;
inline ll hash(){
	ll res=0;
	for(int i=1;i<=n;i++) res=res*11+pt[i];
	return res;
}
inline int unzip(ll now){
	int res=0;
	for(int i=n;i;i--) pt[i]=now%11,now/=11;
	for(int i=1;i<=n;i++) res+=pt[i];
	return res&1;
}
int dfs(ll now){
	if(mp.count(now)) return mp[now];
	int per=unzip(now),res=per?INF:-INF;
	for(int i=1;i<=n;i++)
		if(pt[i-1]>pt[i]){
			pt[i]++;
			ll hs=hash();
			per?res=min(res,dfs(hs)-b[i][pt[i]]):res=max(res,dfs(hs)+a[i][pt[i]]);
			pt[i]--;
		}
	mp[now]=res;
	return res;
}
int main(){
	n=read();pt[0]=m=read();
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read();
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) b[i][j]=read();
	for(int i=1;i<=n;i++) lim=lim*11+m;
	mp[lim]=0;
	dfs(0);
	cout<<mp[0];
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值