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

版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/87925907

BZOJ5248

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

猜你喜欢

转载自blog.csdn.net/qq_43346903/article/details/87925907