【迭代博弈+搜索+剪枝】poj-1568--Find the Winning Move
2021-04-14 05:25
标签:mat att main iat 全局 pre none 返回 搜索 题面省略。。。 Input Output Sample Input Sample Output (我给起的名字是博弈搜索算法,其实是极大极小搜索算法!) 【迭代博弈+搜索+剪枝】poj-1568--Find the Winning Move 标签:mat att main iat 全局 pre none 返回 搜索 原文地址:https://www.cnblogs.com/zhazhaacmer/p/8969466.htmlpoj 1568:Find the Winning Move 【迭代博弈+搜索+剪枝】
?
....
.xo.
.ox.
....
?
o...
.ox.
.xxx
xooo
?
....
....
....
.... (再加一组特殊样例)
$#####
(0,1)
#####
大致题意::
解决思路:
注意:
带注释的题解(第二种check()为超时的判断局面的函数): 1 char mp[4][5];
2 int check(int x,int y,char mp[4][5]){ //判定新更改的点(x,y)是否会构成胜利的局面,两斜/横/竖
3 if(x==y&&mp[0][0]!=‘.‘&&mp[0][0]==mp[1][1]&&mp[1][1]==mp[2][2]&&mp[2][2]==mp[3][3])
4 return (mp[0][0]==‘x‘?0:1);
5 if(x+y==3&&mp[0][3]!=‘.‘&&mp[0][3]==mp[1][2]&&mp[1][2]==mp[2][1]&&mp[2][1]==mp[3][0])
6 return (mp[0][3]==‘x‘?0:1);
7 if(mp[x][0]!=‘.‘&&mp[x][0]==mp[x][1]&&mp[x][1]==mp[x][2]&&mp[x][2]==mp[x][3])
8 return (mp[x][0]==‘x‘?0:1);
9 if(mp[0][y]!=‘.‘&&mp[0][y]==mp[1][y]&&mp[1][y]==mp[2][y]&&mp[2][y]==mp[3][y])
10 return (mp[0][y]==‘x‘?0:1);
11 }
12 /* !!下面这种判断是否可以达到结束的局面的方法,时间复杂度高,毕竟把整个图跑了两遍!
13 int check1(char mp[4][5]){ //三种返回值,0表示前者,1表示后者,-1表示平局
14 for(int i=0;i15 if(mp[i][0]!=‘.‘&&mp[i][0]==mp[i][1]&&mp[i][1]==mp[i][2]&&mp[i][2]==mp[i][3])
16 return (mp[i][0]==‘x‘?0:1);
17 }
18 for(int i=0;i19 if(mp[0][i]!=‘.‘&&mp[0][i]==mp[1][i]&&mp[1][i]==mp[2][i]&&mp[2][i]==mp[3][i])
20 return (mp[0][i]==‘x‘?0:1);
21 }
22 if(mp[0][0]!=‘.‘&&mp[0][0]==mp[1][1]&&mp[1][1]==mp[2][2]&&mp[2][2]==mp[3][3])
23 return (mp[0][0]==‘x‘?0:1);
24 if(mp[0][3]!=‘.‘&&mp[0][3]==mp[1][2]&&mp[1][2]==mp[2][1]&&mp[2][1]==mp[3][0])
25 return (mp[0][3]==‘x‘?0:1);
26
27 for(int i=0;i28 for(int j=0;j29 if(mp[i][j]==‘.‘)
30 return -1;
31 }
32 }
33 return 1;//假设整个棋盘全部布满,平局就也是后者赢!
34 }
35 */
36 int check_whole(){ // //判断全局都是点‘.‘,若是则一定是平局,此种特例不特判必定超时
37 for(int i=0;i3;i++){
38 for(int j=0;j3;j++)
39 if(mp[i][j]!=‘.‘)
40 return false;
41 }
42 return true;
43 }
44 int ansx,ansy;//记录第一次下的点的x和y坐标,也就是step=0的时候!
45
46 bool dfs(int x,int y,int op,int step){//对于op来说,先手X: 0要求必赢,后手1要求不败即可!
47 char ch = (op==0)?‘x‘:‘o‘;
48
49 int val=check(x,y,mp);
50 if(val==op)
51 return true;
52 else if(val==!op)
53 return false;
54
55 for(int i=0;i3;i++){
56 for(int j=0;j3;j++){
57 if(mp[i][j]==‘.‘){
58 mp[i][j]=ch;
59 if(dfs(i,j,!op,step+1)==false){
60 mp[i][j]=‘.‘;
61 // printf("****step=%d****%d,%d ch=%c\n",step,i,j,(op==0)?‘x‘:‘o‘);
62 if(step==0){
63 ansx=i;ansy=j;
64 }
65 return true;
66 }
67 mp[i][j]=‘.‘;
68 }
69 }
70 }
71
72 return false;
73 }
74
75 int main(){
76 char ch[2];
77 while(scanf("%s",ch),ch[0]!=‘$‘){
78 for(int i=0;i3;i++)
79 scanf("%s",mp[i]);
80 if(check_whole()==true)//特判一次!全图都为点时,不忽略的话注定超时!
81 printf("#####\n");
82 else if(dfs(0,0,0,0)==true)
83 printf("(%d,%d)\n",ansx,ansy);
84 else
85 printf("#####\n");
86 }
87
88 return 0;
89 }
文章标题:【迭代博弈+搜索+剪枝】poj-1568--Find the Winning Move
文章链接:http://soscw.com/index.php/essay/75517.html