这道题是 剪枝。
首先,你需要了解什么是 剪枝。
图片直接扒 OIWIKI 的了。
不保证本人理解正确无误。
Minimax
首先引入是一个叫 Minimax 算法的东西。
现在在一个树的顶端,先手需要让答案更大,而后手需要让答案更小,每一次一个人可以选择一颗子树向下移动。
这一个问题可以直接在树上每一个节点找出这个节点的答案,然后根节点就是最后的答案。
图中方框节店会选择最大的子节点移动,而圆形节点会选择最小的节点向后移动,于是就建出了树。
Alpha–Beta 剪枝
刚刚的方法很好,但是当数据范围很大的时候,这个树可能就建不出来了,所以有一个剪枝:Alpha–Beta 剪枝。
看一下大概的思路:
我们每一次走到一个节点,会向下遍历,然后此时,我们就需要记录一些信息。
我们记录下 和 ,表示最小能够获得的和最大能够获得的答案。
比如这张图中,下面的 A 节点,遍历过 之后发现 很小,所以答案不可能大于 了,将 设置成 。
那这样有什么用呢?
看这张图:
途中我们算出了 A 然后现在上传到 B,由于 A 的 为 ,所以 B 的答案不小于 ,将 B 的 设置成 。
然后此时我们再来算 C 节点,要想对 B 有贡献,至少要提供 ,然后我们访问 C 中大小为 的节点,发现最大能提供的只有 ,了,所以矛盾,C 的其他节点不用访问了。
通过这种操作,我们就可以省去很多不必要的搜索。
好像也不是很难?
此题思路
这道题中,我们就设计答案为 和 ,先手需要让答案变成 。操作就是向里面循环枚举每一个空的点位填数,然后来模拟遍历上面讲的树。
代码
轻微压行,还是可读。
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,y;
};
char c[4][4];
string s,q[110];
int tot=0;
bool check(char c[4][4],char p){
for(int i=0;i<4;i++){
if(c[i][0]==p&&c[i][1]==p&&c[i][2]==p&&c[i][3]==p)return 1;
if(c[0][i]==p&&c[1][i]==p&&c[2][i]==p&&c[3][i]==p)return 1;
}
if(c[0][0]==p&&c[1][1]==p&&c[2][2]==p&&c[3][3]==p)return 1;
if(c[0][3]==p&&c[1][2]==p&&c[2][1]==p&&c[3][0]==p)return 1;
return 0;
}
bool full(char c[4][4]){
for(int i=0;i<4;i++)for(int j=0;j<4;j++)if(c[i][j]=='.')return 0;
return 1;
}
int ab(char c[4][4],int a,int b,bool m){
if(check(c,'x'))return 1;
if(check(c,'o'))return -1;
if(full(c))return 0;
int mn=1e9,mx=-1e9;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++)if(c[i][j]=='.'){
char t[4][4];
for(int x=0;x<4;x++)for(int y=0;y<4;y++)t[x][y]=c[x][y];
if(m)t[i][j]='x';
else t[i][j]='o';
int go=ab(t,a,b,m^1);
if(m){
mx=max(mx,go);
a=max(a,go);
}else{
mn=min(mn,go);
b=min(b,go);
}
if(b<=a)break;
}
if(b<=a)break;
}
return (m?mx:mn);
}
node solve(char c[4][4]){
for(int i=0;i<4;i++)for(int j=0;j<4;j++)if(c[i][j]=='.'){
char t[4][4];
for(int x=0;x<4;x++)for(int y=0;y<4;y++)t[x][y]=c[x][y];
t[i][j]='x';
if(check(t,'x'))return {i,j};
if(ab(t,-1e9,1e9,0))return {i,j};
}
return {-1,-1};
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
string s;
while(getline(cin,s)&&s[0]!='$'){
while(s[0]==0)getline(cin,s);
if(s[0]=='$')break;
for(int i=0;i<4;i++)for(int j=0;j<4;j++){
cin>>c[i][j];
}
node ans=solve(c);
if(ans.x==-1)cout<<"#####\n";
else cout<<"("<<ans.x<<","<<ans.y<<")"<<'\n';
}
return 0;
}