试题编号: | 201803-4 |
试题名称: | 棋局评估 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 Alice和Bob正在玩井字棋游戏。 输入格式 输入的第一行包含一个正整数T,表示数据的组数。 输出格式 对于每组数据,输出一行一个整数,表示当前局面的得分。 样例输入 3 样例输出 3 样例说明 第一组数据: 数据规模和约定 对于所有评测用例,1 ≤ T ≤ 5。 |
大一的时候去参加认证看见这道题是一脸懵逼,完全不知道怎么下手。
后来才知道有一种东西叫做对抗搜索。
详细见上一篇博客。
解题思路:两个人轮流下alc 希望分数更高 而bob希望分数更小,在两人都使用最有策略的情况下,明显是一个对抗搜索。
对每一个局势进行评估。
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
#include<cmath>
#include<stdlib.h>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define LL long long
#define N 10005
#define MAXN 2000005
#define inf 0x3f3f3f3
int a[5][5];
int sum()
{
int s=1;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
if(a[i][j]==0)s++;
}
return s;
}
int evaluate()
{
int s1,s2,s3,s4;
for(int i=1;i<=3;i++)
{
s1=0,s2=0,s3=0,s4=0;
for(int j=1;j<=3;j++)
{
if(a[i][j]==1)
s1++;
if(a[i][j]==2)
s2++;
if(a[j][i]==1)
s3++;
if(a[j][i]==2)
s4++;
}
if(s1==3||s3==3)
return sum();
if(s2==3||s4==3)
return -1*sum();
}
s1=0,s2=0,s3=0,s4=0;
for(int i=1;i<=3;i++)
{
if(a[i][i]==1)
s1++;
if(a[i][3-i+1]==1)
s2++;
if(a[i][i]==2)
s3++;
if(a[i][3-i+1]==2)
s4++;
}
if(s1==3||s2==3)return sum();
if(s3==3||s4==3)return -1*sum();
return 0;
}
int minimax(int dep,int now,int alp,int bet)
{
int flag=evaluate();
if(flag||dep==0)//如果有一方赢了或者棋盘已经下满 返回当前的评估值 即对应决策树上的叶子节点
return flag;
if(now)
{
int val=-10;
for(int i=0;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(a[i][j]==0)
{
a[i][j]=1;
val=max(val,minimax(dep-1,!now,alp,bet));
a[i][j]=0;
alp=max(alp,val);
if(alp>=bet)return alp;//alp剪枝
}
}
}
return alp;
}
else
{
int val=10;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(a[i][j]==0)
{
a[i][j]=2;
val=min(val,minimax(dep-1,!now,alp,bet));
a[i][j]=0;
bet=min(bet,val);
if(bet<=alp)return bet;// bet剪枝
}
}
}
return bet;
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
int dep=0;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
sca(a[i][j]);
if(a[i][j]==0)dep++;
}
}
printf("%d\n",minimax(dep,1,-10,10));
}
}