《對弈程序基本技術》專題 最小-最大搜索:http://www.xqbase.com/computer/search_minimax.htm
《對弈程序基本技術》專題 Alpha-Beta搜索 :http://www.xqbase.com/computer/search_alphabeta.htm
Wikipedia MinMax :http://en.wikipedia.org/wiki/Minimax
Wiki Alpha–beta pruning :http://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning
Minmax Explained:http://ai-depot.com/articles/minimax-explained/1/
講解極小極大 (Minimax Explained) [譯] :http://www.starming.com/index.php?action=plugin&v=wave&tpl=union&ac=viewgrouppost&gid=34694&tid=15725
最小最大原理與搜索方法:http://blog.pfan.cn/rickone/16930.html
個人理解:
在博弈中夠找一顆博弈樹,每層的節點在同一個狀態,別且每個節點都有一個取勝的評估值,分為max狀態和min狀態,比如玩家A對應max狀態,玩家B對應min狀態。目的是A要使自己的評估值最大,B要使自己的評估值最小(B的評估值用負數表示,這樣方便理解)。
max狀態要走到min狀態選擇什么樣的路徑呢?先不要從玩家A自身的着點考慮,從A的角度去看B,如果A這樣着點,估計B會走哪些狀態得到的min值情況如何,然后從中選擇一個B所有min值中最大的那個(負數最大,絕對值最小),顯然這樣對A是最有利的。孫子有雲“知己知彼,百戰不怠也”~
對B來說同樣也是如此,如果AB的水平一樣的話,那結果就取決於先手和后手了,所以結果會有唯一解。
關於alpha-beta剪枝。還是站在A的角度考慮。A要取使得B的所有min值中最大(負數)的那個狀態,那可以對事先得到過的最小狀態做一個記錄,如果出現比最大(負數)的那個狀態小的,則這個分支就可以被減掉,這是alpah剪枝。同理,從B的角度考慮就是去max值最小的,這是beta剪枝。
只能理解這么多了。。。看論文快看哭了。。。吾要學好英語,English...應該累死!!!
POJ 1085
題意:AB輪流在包含9個小三角形的大三角形中放邊,當某人放上一條邊后構成一個小三角形,則這個人得一分,誰得的分多誰就贏了。
maxmin搜索 + alpha-beta剪枝,過程是對這個大三角形就行壓縮,共17條邊。然后搜索。這個題里,alpha為1,表示A可以贏,出現搜索值返回的是1的時候其他的就不用再搜了。beta值為-1,表示B可以贏,同理進行剪枝。
參考:http://blog.csdn.net/dooder_daodao/article/details/6682971

//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); typedef long long LL; const double eps = 1e-8; const double PI = acos(-1.0); const int inf = ~0u>>2; using namespace std; //棋盤上17個點,兩個點構成一條邊,給邊編號,mat[a][b]表示a->b這條邊對應的編號。 int mat[11][11]={ {0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,1,0,0,0,0,0,0,0}, {0,0,0,2,3,4,0,0,0,0,0}, {0,1,2,0,0,5,6,0,0,0,0}, {0,0,3,0,0,7,0,9,10,0,0}, {0,0,4,5,7,0,8,0,11,12,0}, {0,0,0,6,0,8,0,0,0,13,14}, {0,0,0,0,9,0,0,0,15,0,0}, {0,0,0,0,10,11,0,15,0,16,0}, {0,0,0,0,0,12,13,0,16,0,17}, {0,0,0,0,0,0,14,0,0,17,0} }; //把三條邊能夠構成的三角形狀態壓縮 int tri[9]={7,152,52,352,34304,3200,71680,12544,155648}; int FULL = (1<<18) - 1; int Max_search(int state, int alpha, int ca, int cb); int Min_search(int state, int beta, int ca, int cb); int new_status(int old, int seg, int& cnt) { int _new = old|seg; for(int i = 0; i < 9; ++i) { if((old&tri[i]) != tri[i] && (_new&tri[i]) == tri[i]) { cnt++; } } return _new; } int Max_search(int state, int alpha, int ca, int cb) { if(ca >= 5) return 1; if(cb >= 5) return -1; if(state == FULL) return ca > cb ? 1 : -1; int _new, seg, tmp, ta, ans = -1; int bit = (~state)&FULL; while(bit) { seg = bit&(-bit); ta = ca; _new = new_status(state, seg, ta); if(ta > ca) tmp = Max_search(_new, alpha, ta, cb); else tmp = Min_search(_new, ans, ta, cb); if(tmp > ans) ans = tmp; if(tmp >= alpha) return ans; //A存在能夠勝利的狀態,直接return bit -= seg; } return ans; } int Min_search(int state, int beta, int ca, int cb) { if(ca >= 5) return 1; if(cb >= 5) return -1; if(state == FULL) return ca > cb ? 1 : -1; int _new, seg, tmp, tb, ans = 1; int bit = (~state)&FULL; while(bit) { seg = bit&(-bit); tb = cb; _new = new_status(state, seg, tb); if(tb > cb) tmp = Min_search(_new, beta, ca, tb); else tmp = Max_search(_new, ans, ca, tb); if(tmp < ans) ans = tmp; if(tmp <= beta) return ans; //B存在能夠勝利的狀態 bit -= seg; } return ans; } int main() { //Read(); int T, n, a, b, ans, cas = 0; int cnt, status, ca, cb, ta, tb; cin >> T; while(T--) { cin >> n; cnt = status = 0; ca = cb = 0; while(n--) { cin >> a >> b; ta = ca; tb = cb; status = new_status(status, 1<<mat[a][b], (cnt&1)?cb:ca); if(ta == ca && tb == cb) cnt++; } if(cnt&1) ans = Min_search(status, -1, ca, cb); //輪到B走 else ans = Max_search(status, 1, ca, cb); //輪到A走 printf("Game %d: %s\n", ++cas, ans == 1 ? "A wins." : "B wins."); } return 0; }