【胡搞的不能AC的题解,暴力搜索一发博弈问题】1995 三子棋 - 51Nod
原题链接: 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 }
友情提示这不是题解!没法判断是否可以达到平局的局面,但这题不存在平局的局面;想判断的话,可以用调用game函数的次数来判断!(可能吧!)
像这类博弈问题基本都是找规律的,找不出来规律就没法了!除非很水的题!
你不逼自己一把,你永远都不知道自己有多优秀!只有经历了一些事,你才会懂得好好珍惜眼前的时光!