【CCF 201803-4】棋局評估(對抗搜尋)
阿新 • • 發佈:2019-01-09
思路
①當Alice下的時候,我們嘗試所有可能的下法,並找到所有下法中使結果最大的一個
當Bob下的時候,我們嘗試所有可能的下法,並找到所有下法中使結果最小的一個
②輪流執子,直到雙方有人勝利或棋盤填滿
蒟蒻我還是不能很好的表達出意思來...QAQ
C++滿分程式碼(帶註釋)
#include <iostream> using namespace std; const int inf = 1e8; int chess[3][3]; inline int Score() //返回棋局的得分,若未結束則返回inf { int blank = 0; //空格數 for(int i=0; i<3; ++i) for(int j=0; j<3; ++j) if(chess[i][j] == 0) ++blank; int flag = (blank & 1 ? -1 : 1); //空格數為偶數,說明走了奇數步,這時Bob可能要贏了,故flag=-1 for(int i=0; i<3; ++i) if(chess[i][0]==chess[i][1] && chess[i][1]==chess[i][2] && chess[i][0]) return flag*(blank+1); for(int j=0; j<3; ++j) if(chess[0][j]==chess[1][j] && chess[1][j]==chess[2][j] && chess[2][j]) return flag*(blank+1); if(chess[0][0]==chess[1][1] && chess[1][1]==chess[2][2] && chess[2][2]) return flag*(blank+1); if(chess[2][0]==chess[1][1] && chess[1][1]==chess[0][2] && chess[0][2]) return flag*(blank+1); if(blank == 0) return 0; //如果沒人贏,又下滿了,則為平局 return inf; } inline int search(int a) //下面以Alice為例進行說明,Bob在(*)處正好相反 { int score = Score(); if(score != inf) return score; //若結束,返回分數 int optimal = (a == 1 ? -inf : inf), tmp; //optimal初始化為-inf,Alice要使optimal達到最大 (*) for(int i=0; i<3; ++i) for(int j=0; j<3; ++j) { if(chess[i][j] == 0) //對所有空格子進行嘗試 { chess[i][j] = a; tmp = (a == 1 ? search(2) : search(1)); //Alice下完Bob下 (*) if(a == 1) optimal = max(tmp, optimal); //optimal取較大者 (*) else optimal = min(tmp, optimal); chess[i][j] = 0; //嘗試之後記得復原 } } return optimal; } int main() { ios::sync_with_stdio(false); int t; cin>>t; while(t--) { for(int i=0; i<3; ++i) //輸入 for(int j=0; j<3; ++j) cin>>chess[i][j]; cout<<search(1)<<"\n"; //輸出 } return 0; }