POJ Find the Winning Move【minmax搜索+alpha-beta剪枝】【北大ACM/ICPC竞赛训练】

  1 #include<iostream>
  2 using namespace std;
  3
  4 int row,col,chess;
  5 char board[5][5];
  6
  7 int minSearch(int i,int j,int alpha);
  8 int maxSearch(int i,int j,int beta);
  9
 10
 11 bool check(int r,int c){
 12     if( board[r][0]==board[r][1] && board[r][1]==board[r][2] && board[r][2]==board[r][3] && board[r][3]!=‘.‘ ) return true;
 13     if( board[0][c]==board[1][c] && board[1][c]==board[2][c] && board[2][c]==board[3][c] && board[3][c]!=‘.‘ ) return true;
 14
 15     if( board[0][3]==board[1][2] && board[1][2]==board[2][1] && board[2][1]==board[3][0] && board[0][3]==board[r][c] ) return true;
 16     if( board[0][0]==board[1][1] && board[1][1]==board[2][2] && board[2][2]==board[3][3] && board[0][0]==board[r][c] ) return true;
 17     return false;
 18 }
 19
 20 int minSearch(int i,int j,int alpha){ //minsearch返回所有子结点中的【最小值】  alpha代表它父亲兄弟结点的最大值
 21     //上一步走在了(i,j),要判断【这个棋子】能不能让棋局结束
 22     if( check(i,j) ) return 1;//x下完就结束了,x胜
 23     if( chess==16 ) return 0;
 24
 25
 26
 27
 28     int beta = 1;//这个里面放所以子结点的最小值 == 因为是min结点 == 一开始得很大
 29     for(int i=0;i<4;i++)
 30         for(int j=0;j<4;j++)
 31             if( board[i][j]==‘.‘ ){
 32                 board[i][j] = ‘o‘; chess++;
 33
 34                 beta = min(beta, maxSearch(i,j,beta) );//第三个参数是 == 目前min结点兄弟结点中的最小值
 35
 36                 board[i][j] = ‘.‘; chess--;
 37                 if( alpha>= beta ) return beta;
 38             }
 39     return beta;
 40 }
 41
 42 int maxSearch(int i,int j,int beta){//beta是上一层兄弟结点中的最小值
 43     if( check(i,j) ) return -1;
 44     if( chess==16 ) return 0;
 45
 46     int alpha = -1;//记录所有子结点中的最大值
 47     for(int i=0;i<4;i++)
 48         for(int j=0;j<4;j++)
 49             if( board[i][j]==‘.‘ ){
 50                 board[i][j] = ‘x‘; chess++;
 51
 52                 alpha = max( alpha,minSearch(i,j,alpha) );//alpha是我兄弟结点的最大值
 53
 54                 board[i][j] = ‘.‘; chess--;
 55                 if( alpha>=beta ) return alpha;
 56             }
 57     return alpha;
 58 }
 59
 60
 61
 62 bool solve(){
 63
 64     int alpha=-1;//一开始最大值很小 == 根结点 == 根结点的子结点都剪不了
 65     for(int i=0;i<4;i++)
 66         for(int j=0;j<4;j++)
 67             if( board[i][j]==‘.‘ ){
 68                 board[i][j] = ‘x‘; chess++;
 69
 70                 int tmp = minSearch(i,j,alpha);//第三个是alpha代表它兄弟结点的最大值 , 但root没有兄弟节点
 71
 72                 board[i][j] = ‘.‘; chess--;
 73             //    cout<<i<<" "<<j<<" "<<tmp<<endl;
 74                 //cout<<i<<" "<<j<<endl;
 75                 if(tmp==1) { row=i; col=j; return true; }
 76             }
 77
 78     return false;
 79 }
 80
 81
 82 int main(){
 83
 84
 85     while(1){
 86         chess=0;
 87         char op; cin>>op;
 88         if(op==‘$‘) break;
 89         for(int i=0;i<4;i++)
 90             for(int j=0;j<4;j++) {
 91                 cin>>board[i][j];
 92                 if(board[i][j]!=‘.‘) chess++;
 93             }
 94
 95         if( solve() ) cout<<"("<<row<<","<<col<<")"<<endl;
 96         else cout<<"#####"<<endl;
 97     }
 98
 99
100 }

原文地址:https://www.cnblogs.com/ZhenghangHu/p/9386138.html

时间: 2024-10-08 15:16:35

POJ Find the Winning Move【minmax搜索+alpha-beta剪枝】【北大ACM/ICPC竞赛训练】的相关文章

POJ 6048 泰国佛塔 【dfs搜索】【疯狂剪枝!】【北大ACM/ICPC竞赛训练】

1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 5 int volumn[25],minArea[25];//volumn[i]为第i层到第1层蛋糕所用最小体积 6 int ans,n,m; //minArea[i]为第i层到第1层蛋糕所用[最小侧面积] 7 int area;//当前dfs状态所需要用的表面积 8 9 int maxV(int level,int r,int h){//用level层蛋

POJ 4979 海贼王之伟大航路 【状压dp】【北大ACM/ICPC竞赛训练】

该死的题让我想起来艾斯之死... 首先想到dp(i)代表从1到[i表示的这些岛屿]所花的最小时间,然后每次枚举最后一个岛屿以此缩小范围,但发现枚举了最后一个岛屿后没有办法转移,因为不知道倒数第二个岛屿是什么,随着倒数第二个岛屿的不同,时间的增加也会不同,也就是不具备[无后效性]. 因此想到再加一个参数去约束当前问题的状态,dp(i,j)代表1到[i代表的这些点]所需的最少时间,且这趟旅程的最后一个岛屿是j,这样就可转移了,每次枚举倒数第二岛屿:答案就是dp( (1<<n) -1,n ) 具体的

HDU 5025 Saving Tang Monk【bfs搜索】【北大ACM/ICPC竞赛训练】

bfs的难点在于怎么去表示一个问题的状态[也就是如何去判重] 1 #include<iostream> 2 #include<queue> 3 #include<cstring> 4 #include<map> 5 using namespace std; 6 7 struct node{ 8 int r,c; 9 int keys; 10 int kill;//记录当前杀死守卫的状态 11 int d;//时间 12 bool operator <

POJ 8471 切割回文 【dp】【北大ACM/ICPC竞赛训练】

1 #include<iostream> 2 #include<vector> 3 #define INF 100000 4 using namespace std; 5 6 string s; 7 char a[1005]; 8 vector<int> hui[1005];//hui[i]里的k指 k到i组成回文 9 int dp[1005];//dp[i]代表前i个字符要切几刀 10 11 int main(){ 12 int t; cin>>t; 13

POJ 1194 Zipper 【dp】【北大ACM/ICPC竞赛训练】

现在做dp题有点感觉了,以前估计会觉得这题很难,现在觉得这是道不是很水的水题 dp[i][j]代表A里前i个加上B里前j个能不能组成C的前i+j个. 至于怎么想到的呢,n是200,有1000组数据,所以猜测要dp二维,然后很容易就想到了. 这里再考虑到C[i+j]的这个元素肯定是由A[i]或B[j]组成(即A的最末尾或B的最末尾,因为要保证原来的order) 所以这就变成了dp[i][j] = dp[i-1][j] | dp[i][j-1]  (当然这是A[i]=B[j]=C[i+j])的情况.

POJ 3436 ACM Computer Factory 【网络流】【北大ACM/ICPC竞赛训练】

我ac掉网络流的第一题! 先总结一下网络流的一些算法吧,首先是Ford-Fulkerson算法,这个算法是保证了众多网络流算法的[正确性],其他算法也是基于其[优化]得到的.Ford的算法在于引入"反向边"的概念,反向边就是反悔边,代表你给修正以前走了的边一个机会.为什么反向边是对的呢,凭空加进来一条边真的大丈夫吗,关于这个有相关正确性的证明,我也说不清楚只能直觉上去理解. 之后是Edmonds-Karp即最短增广路算法,顾名思义,每次都找到达汇点边数最少的增广路,由此避免一些特定的消

五子棋AI算法第三篇-Alpha Beta剪枝

剪枝是必须的 上一篇讲了极大极小值搜索,其实单纯的极大极小值搜索算法并没有实际意义. 可以做一个简单的计算,平均一步考虑 50 种可能性的话,思考到第四层,那么搜索的节点数就是 50^4 = 6250000,在我的酷睿I7的电脑上一秒钟能计算的节点不超过 5W 个,那么 625W 个节点需要的时间在 100 秒以上.电脑一步思考 100秒肯定是不能接受的,实际上最好一步能控制在 5 秒 以内. 顺便说一下层数的问题,首先思考层数必须是偶数.因为奇数节点是AI,偶数节点是玩家,如果AI下一个子不考

poj1568 Find the Winning Move[极大极小搜索+alpha-beta剪枝]

Find the Winning Move Time Limit: 3000MS   Memory Limit: 32768K Total Submissions: 1286   Accepted: 626 Description 4x4 tic-tac-toe is played on a board with four rows (numbered 0 to 3 from top to bottom) and four columns (numbered 0 to 3 from left t

C++alpha beta剪枝算法 实现4*4 tic-tac-toe

先上一张alpha beta原理图,一看就懂 代码有点长,主要是因为算评估值得时候用的是穷举. 玩家是1,电脑是2,可以选择难度以及先手. // // main.cpp // Tic-Tac-Toe // // Created by mac on 2017/4/2. // Copyright ? 2017年 mac. All rights reserved. // #include <iostream> #include <vector> #include <math.h&g