题目链接:点击打开链接
题目大意:给出一个4*4棋盘,问你x先手的情况下,是否能实现必胜(胜利条件是横着或竖着或斜着出现四连)
题目思路:第一道极大极小值搜索题目...首先一个强大的剪枝,如果下的步数小于等于4,那么肯定可以平局(好像是井字棋特性),然后极大极小值搜索。
极大极小值搜索介绍:
极大极小值搜索靠的是返回的数值,每个人下一步,到最后如果返回1就说明必胜,否则就不一定必胜。因为要判断是否必胜,所以每一步都要走一下,step表示还能走几步。然后首先先找一下有没有可以下的点,有的话就下下去,然后递归下一步,给对方下,刚开始要写个value函数,就是判断当前局面有没有人赢了。val是用来看后面状态的情况,z是当前的情况,刚开始先把z变成不利于己方的情况,然后不断递归,看下面的局势,如果后面可以必胜,那z就会通过val的值不断更新,后面如果赢了或者输了前面就能知道了。
以下是代码:
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char cmd[1],map1[10][10],x,y;
int value(){
int h1,h2,s1,s2;
for(int i=0;i<4;i++){
h1=0,h2=0,s1=0,s2=0;
for(int j=0;j<4;j++){
if(map1[i][j]=='x'){
h1++;
}
if(map1[i][j]=='o'){
h2++;
}
if(map1[j][i]=='x'){
s1++;
}
if(map1[j][i]=='o'){
s2++;
}
}
if(h1==4||s1==4){
return 1;
}
if(h2==4||s2==4){
return -1;
}
}
h1=0,h2=0,s1=0,s2=0;
for(int i=0;i<4;i++){
if(map1[i][i]=='x'){
h1++;
}
if(map1[i][i]=='o'){
h2++;
}
if(map1[i][3-i]=='x'){
s1++;
}
if(map1[i][3-i]=='o'){
s2++;
}
}
if(h1==4||s1==4)return 1;
if(h2==4||s2==4)return -1;
return 0;
}
int Max(int);
int Min(int step){
int flag=value(),z=1,val;
if(flag||step==0){
return flag;
}
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(map1[i][j]=='.'){
map1[i][j]='o';
val=Max(step-1);
map1[i][j]='.';
z=min(val,z);
}
}
}
return z;
}
int Max(int step){
int val,z=-1,flag=value();
if(flag||step==0){
return flag;
}
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(map1[i][j]=='.'){
map1[i][j]='x';
val=Min(step-1);
map1[i][j]='.';
z=max(z,val);
if(val==1){
x=i,y=j;
return 1;
}
}
}
}
return z;
}
int main()
{
while(~scanf("%s",cmd)&&cmd[0]!='$'){
int step=0;
for(int i=0;i<4;i++){
scanf("%s",map1[i]);
for(int j=0;j<4;j++){
if(map1[i][j]=='.'){
step++;
}
}
}
if(step>11){
printf("#####\n");
continue;
}
int z=Max(step);
if(z==1){
printf("(%d,%d)\n",x,y);
}
else{
printf("#####\n");
}
}
return 0;
}