Time Limit: 3000MS | Memory Limit: 32768K | |
Total Submissions: 421 | Accepted: 240 |
Description
Input
Output
Sample Input
? .... .xo. .ox. .... ? o... .ox. .xxx xooo $
Sample Output
##### (0,1)
Source
极大极小搜索策略一般都是使用在一些博弈类的游戏之中:
这样策略本质上使用的是深度搜索策略,所以一般可以使用递归的方法来实现。在搜索过程中,对本方有利的搜索点上应该取极大值,而对本方不利的搜索点上应该取极小值。
极小值和极大值都是相对而言的。
在搜索过程中需要合理的控制搜索深度,搜索的深度越深,效率越低,但是一般来说,走法越好。
极大极小搜索可以分开写,也可以放在一起写。
#include <iostream> #include <memory.h> #include <stdio.h> using namespace std; #define inf 100000000 int state[5][5],chess,xi,xj; char ch; int minfind(int,int,int); int maxfind(int,int,int); bool over(int x,int y) { bool flag = false; int row[5],col[5]; memset(row,0,sizeof(row)); memset(col,0,sizeof(col)); for (int i=0;i<4;i++) for (int j=0;j<4;j++) { if (state[i][j]=='x') { row[i]++; col[j]++; } if (state[i][j]=='o') { row[i]--; col[j]--; } } if (row[x]==-4 || row[x]==4 || col[y]==-4 || col[y]==4) flag = true; int tot1 = 0, tot2 = 0; for (int i=0;i<4;i++) { if (state[i][i]=='x') tot1++; if (state[i][3-i]=='x') tot2++; if (state[i][i]=='o') tot1--; if (state[i][3-i]=='o') tot2--; } if ((tot1==4 || tot1==-4) && x==y) flag = true; if ((tot2==4 || tot2==-4) && x==3-y) flag = true; return flag; } int maxfind(int x,int y,int mini) { int tmp, maxi = -inf; if (over(x,y)) return maxi; if (chess==16) return 0; for (int i=0;i<4;i++) for (int j=0;j<4;j++) if (state[i][j]=='.') { state[i][j]='x'; chess++; tmp = minfind(i,j,maxi); chess--; state[i][j]='.'; maxi = max(maxi, tmp); if (maxi>=mini) return maxi;// f(p)正无穷,先手必胜 } return maxi; } int minfind(int x,int y,int maxi) { int tmp, mini = inf; if (over(x,y)) return mini; if (chess==16) return 0; for (int i=0;i<4;i++) for (int j=0;j<4;j++) if (state[i][j]=='.') { state[i][j]='o'; chess++; tmp = maxfind(i,j,mini); chess--; state[i][j]='.'; mini = min(mini, tmp); if (mini<=maxi) return mini;//f(p)负无穷,后手必胜 } return mini; } bool tryit() { int tmp, maxi = -inf; for (int i=0;i<4;i++) for (int j=0;j<4;j++) if (state[i][j]=='.') { state[i][j] = 'x'; chess++; tmp = minfind(i,j,maxi); chess--; state[i][j] = '.'; if (tmp>=maxi) { maxi = tmp; xi = i; xj = j; } if (maxi==inf) return true;//f(p)正无穷,先手必胜 } return false; } int main() { while (scanf("%c",&ch)) { if (ch=='$') break; scanf("%c",&ch); chess = -4; for (int i=0;i<4;i++) for (int j=0;j<5;j++) { scanf("%c",&state[i][j]); chess += state[i][j]!='.'; } if (chess<=4) { //强力剪枝 printf("#####\n"); continue; } if (tryit()) printf("(%d,%d)\n",xi,xj); else printf("#####\n"); } return 0; }
Alpha-Beta搜索剪枝算法如下:
输入:搜索深度、alpha、beta
输出:节点的最佳走法、及对应的最佳估值
函数形式:int alphaBetaSearch(int depth ,int alpha,int beta)
如果depth小于等于0
调用评估函数,并将结果赋给value
返回value值
否则
生成当前所有合理的走法
对每一个走法
执行走法
value= - alphaBetaSearch( depth-1 , -beta , -alpha);
//注意函数前面有负值,且参数alpha,beta分别取负值并进行交换
撤销走法
如果 value>=beta //使得可能引起的走法先被搜索,因为搜索的效率很大程度上取决于剪枝的效果
返回beta
如果 value>alpha
alpha=value
如果 depth == Max_Depth
bestmove=mv
返回alpha
调用形式:alphaBetaSearch(MaxDepth,-MaxValue,MaxValue)
写的代码跟这个思想不完全一样
#include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <map> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int inf=(1<<30); const int N=25; int pw2[25],pw3[25]; map<int,int>rpw2; //--------------------------------------------------------- struct point { int x,y; }pt[N]; int m; char g[5][5]; int ansx,ansy,score; int ans[N],ct; int hash[555555]; const int n=4; bool check(int x,int y) { int i=0; while(i<4&&g[x][i]==g[x][y]) i++;if(i>=4) return true;i=0; while(i<4&&g[i][y]==g[x][y]) i++;if(i>=4) return true;i=0; if(x==y) while(i<4&&g[i][i]==g[x][y]) i++;if(i>=4) return true;i=0; if(x+y==3) while(i<4&&g[i][3-i]==g[x][y]) i++;if(i>=4) return true; return false; } int maxmin(int state,int who,int now,int alpha,int beta,int dep) { if(hash[now]!=-inf) return hash[now]; if(state==0) return hash[now]=0;/// int maxval=-inf,minval=inf,val; for(int st=state;st;st-=st&(-st)) { int i=st&(-st),x=rpw2[i]; g[pt[x].x][pt[x].y]=(who==0?'x':'o'); if(check(pt[x].x,pt[x].y)) val=who^1; else val=maxmin(state-i,who^1,now+(who+1)*pw3[x],maxval,minval,dep+1); g[pt[x].x][pt[x].y]='.'; if(who==0&&val>beta) return val; if(who==1&&val<alpha) return val; maxval=max(maxval,val); minval=min(minval,val); if(dep==0&&val>0) { if(ansx>pt[x].x||(ansx==pt[x].x&&ansy>pt[x].y)) { ansx=pt[x].x; ansy=pt[x].y; } } } if(who==0) return hash[now]=maxval; else return hash[now]=minval; } void init() { pw2[0]=pw3[0]=1; rpw2.clear(); for(int i=0;i<20;i++) pw2[i]=1<<i,rpw2[1<<i]=i; for(int i=1;i<15;i++) pw3[i]=pw3[i-1]*3; } int main() { int i,j,t,cas=0; int st; char c[5]; init(); while(cin>>c) { if(c[0]=='$') break; m=0; for(i=0;i<n;i++) { scanf("%s",g[i]); for(j=0;j<n;j++) { if(g[i][j]=='.')pt[m].x=i,pt[m++].y=j; } } st=pw2[m]-1; //111111 //score=-inf; for(i=0;i<pw3[m];i++) hash[i]=-inf; ansx=inf;/// int ret=maxmin(st,0,0,-inf,inf,0); if(ret==0) puts("#####"); else printf("(%d,%d)\n",ansx,ansy); } return 0; } /* 4 01.1 00.. .01. ...1 4 0.01 0.01 1..0 .1.. 0 */