试题编号: 201803-4 试题名称: 棋局评估 (对抗搜索 博弈)

6 篇文章 0 订阅

这题真的是一道很不错的题,首先我对题意的理解有点问题,我以为的最优策略是,用最优的策略取胜,但是题目的意思是用最优的策略取得最好的得分。
到哪个人行棋,就暴搜哪个人的可选的每一步,然后比较下一个人行棋所得的结果,取最优。
例如当alice行棋时,就让alice下一步棋的得分取bob最优行棋的分数,然后alice有不同的点可以下,就让alice下一步走法的最优解等于alice走完下一步之后,对应的bob走下一步时的最优解中的最大值。
也就相当于是

alice下一步有很多中走法, 取bob走出最优解中最大的得分,即bob想得分最小,但是alice就取bob得分最小中的最大值即可。
代码如下
#include <bits/stdc++.h>
using namespace std;
int mp[5][5];
const int INF=0x3f3f3f3f;

int judge()
{
	for (int i=0;i<3;i++) {
		if (mp[i][0]!=0&&mp[i][0]==mp[i][1]&&mp[i][1]==mp[i][2]) return mp[i][0];
		if (mp[0][i]!=0&&mp[0][i]==mp[1][i]&&mp[1][i]==mp[2][i]) return mp[0][i];
	}
	if (mp[0][0]!=0&&mp[0][0]==mp[1][1]&&mp[2][2]==mp[1][1]) return mp[0][0];
	if (mp[2][0]!=0&&mp[2][0]==mp[1][1]&&mp[1][1]==mp[0][2]) return mp[2][0];
	bool flag=true;
	for (int i=0;i<3;i++)
		for (int j=0;j<3;j++) 
			if (mp[i][j]==0)
				flag=false;
	if (flag) return 0;
	return -2;
}

int score()
{
	int cnt=0;
	for (int i=0;i<3;i++) {
		for (int j=0;j<3;j++) {
			if (mp[i][j]==0) {
				cnt++;
			}
		}
	}
	return cnt;
}

int dfs(int p)
{
	int j=judge();
	if (j==0) {
		return 0;
	}
	else if (j==1) {
		return score()+1;
	}
	else if (j==2) {
		return -(score()+1);
	}

	int ans=(p==1)?-INF:INF;
	for (int i=0;i<3;i++) {
		for (int j=0;j<3;j++) {
			if (!mp[i][j]) {
				mp[i][j]=p;
				if (p==1) {
					ans=max(ans,dfs(2));
				}
				else {
					ans=min(ans,dfs(1));
				}
				mp[i][j]=0;
			}
		}
	}
	return ans;
}

int main()
{
	// freopen("in.txt","r",stdin);
	int T;
	scanf("%d",&T);
	while (T--) {
		for (int i=0;i<3;i++) {
			for (int j=0;j<3;j++) {
				scanf("%d",&mp[i][j]);
			}
		}
		// printf("%d\n",judge());
		printf("%d\n",dfs(1));
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值