【胡搞的不能AC的题解,暴力搜索一发博弈问题】1995 三子棋 - 51Nod

题目来源: syu校赛
基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
原题链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1995

 

小的时候大家一定玩过“井”字棋吧。也就是在九宫格中,只要任意行、列,或者任意连续对角线上面出现三个相同的,就能获胜。现在小明和小花也在玩三子棋,但是他们不是在九宫格里,而是在3×4的格子里面。现在小明先下,但是他知道小花这个人很聪明,他想知道第一步下在哪一个地方最合适,你能帮帮他吗?



Input
第一行输入一个整数T,表示数据组数(1<T<10000); 
第二行输入两个整数x,y,表示3×4格子里面的一个坐标(x,y)(1<=x<=3,1<=y<=4);
Output
每组数据输出最后小明输赢的结果,如果小明一定能赢,第一行输出“Win”,第二行输出小明所需要花的最少步数;如果小明跟小花只能打成平手,第一行输出“Equal”,第二行输出数字0;如果小明不能赢也不能跟小花打成平手,第一行输出“Lose”,第二行输出小花赢小明所需要花的最少步数。
Input示例
2
2 1
2 4
Output示例
Equal
0
Equal
0


-------------------------------------------------------------------------------
看到这个题目我想到了搜索,但计算了一下时间复杂度:不是很大,应该不会超时!但是,这是个博弈问题,暴力穷举的话没法进行模拟!

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<iostream>
  4 #include<stdlib.h>
  5 #include<math.h>
  6 #include<algorithm>
  7 #include<queue>
  8 using namespace std;
  9 #define inf 0x3f3f3f3f
 10 #define emin 1e-10
 11 #define ll long long   //10:19--
 12 int mp[4][5],flag;
 13 int dir[8][2]= { {0,1},{0,-1},{1,0},{1,-1},{1,1},{-1,-1},{-1,0},{-1,1} };
 14 
 15 int check()
 16 {
 17     int i,j;
 18     for(j=1; j<=4; j++) //竖行
 19     {
 20         if(mp[1][j]==mp[2][j]&&mp[2][j]==mp[3][j]&&mp[3][j]!=-1)
 21             return mp[1][j];
 22     }
 23     for(i=1; i<=3; i++) //横行
 24     {
 25         if(mp[i][1]==mp[i][2]&&mp[i][2]==mp[i][3]&&mp[i][3]!=-1)
 26             return mp[i][2];
 27         if(mp[i][2]==mp[i][3]&&mp[i][3]==mp[i][4]&&mp[i][3]!=-1)
 28             return mp[i][2];
 29     }
 30     if(mp[1][1]==mp[2][2]&&mp[2][2]==mp[3][3]&&mp[3][3]!=-1)
 31         return mp[1][1];
 32     if(mp[1][2]==mp[2][3]&&mp[2][3]==mp[3][4]&&mp[3][4]!=-1)
 33         return mp[1][2];
 34     if(mp[1][3]==mp[2][2]&&mp[2][2]==mp[3][1]&&mp[3][1]!=-1)
 35         return mp[1][3];
 36     if(mp[1][4]==mp[2][3]&&mp[2][3]==mp[3][2]&&mp[3][2]!=-1)
 37         return mp[2][3];
 38     return -1; //当前局面无结果
 39 }
 40 void print_mp()
 41 {
 42     for(int i=1; i<=3; i++)
 43     {
 44         for(int j=1; j<=4; j++)
 45             printf("%3d",mp[i][j]);
 46         printf("\n");
 47     }
 48 }
 49             //num=0表示先手下棋者,num=1表示后手下棋者
 50 int game(int step,int num) //当前正要走的的步数step,num表示当前step步下棋者
 51 {
 52     int i,j,k;
 53     if(step==13) //至多12个格子
 54         return -1;
 55     if(k=check(),k!=-1) //不用下棋时就已经达到获胜或者失败的局面了!
 56     {
 57         return k;
 58     }
 59     for(i=1; i<=3; i++)
 60     {
 61         for(j=1; j<=4; j++)
 62         {
 63             if(mp[i][j]==-1)
 64             {
 65                 mp[i][j]=num;
 66 
 67                 if(check()==num) //下完一步后,检验整个棋盘可以获胜则返回
 68                 {
 69                     mp[i][j]=-1;
 70                     return num;  //返回当前局面的获胜者
 71                 }
 72                 if(game(step+1,!num)==num) //后续递归博弈处理可以胜利则返回
 73                 {
 74                     mp[i][j]=-1;
 75                     return num;  //返回当前局面的获胜者
 76                 }
 77                 mp[i][j]=-1;
 78             }
 79         }
 80     }
 81     return !num;
 82 }
 83 
 84 
 85 int main()
 86 {
 87     int a,b,ans;
 88     // init();
 89     for(a=1; a<=3; a++)
 90     {
 91         for(b=1; b<=4; b++)
 92         {
 93             memset(mp,-1,sizeof(mp));
 94             mp[a][b]=0;//先手先下一步
 95             ans=game(2,1);  //调用博弈函数
 96             if(ans==0)
 97                 printf("当a=%d,b=%d, 先手Win\n",a,b);
 98             else
 99                 printf("当a=%d,b=%d, 先手Lose 或者 Equal\n",a,b);
100         }
101     }
102 
103     return 0;
104 }
View Code

友情提示这不是题解!没法判断是否可以达到平局的局面,但这题不存在平局的局面;想判断的话,可以用调用game函数的次数来判断!(可能吧!)

像这类博弈问题基本都是找规律的,找不出来规律就没法了!除非很水的题!

 

posted @ 2017-12-26 14:30  山枫叶纷飞  阅读(495)  评论(0编辑  收藏  举报