201803-4棋局評估_極大極小值演算法_對抗搜尋(轉載)
試題編號: | 201803-4 |
試題名稱: | 棋局評估 |
時間限制: | 1.0s |
記憶體限制: | 256.0MB |
問題描述: | 問題描述 Alice和Bob正在玩井字棋遊戲。 井字棋遊戲的規則很簡單:兩人輪流往3*3的棋盤中放棋子,Alice放的是“X”,Bob放的是“O”,Alice執先。當同一種棋子佔據一行、一列或一條對角線的三個格子時,遊戲結束,該種棋子的持有者獲勝。當棋盤被填滿的時候,遊戲結束,雙方平手。 Alice設計了一種對棋局評分的方法: - 對於Alice已經獲勝的局面,評估得分為(棋盤上的空格子數+1); - 對於Bob已經獲勝的局面,評估得分為 -(棋盤上的空格子數+1); - 對於平局的局面,評估得分為0; 例如上圖中的局面,Alice已經獲勝,同時棋盤上有2個空格,所以局面得分為2+1=3。 由於Alice並不喜歡計算,所以他請教擅長程式設計的你,如果兩人都以最優策略行棋,那麼當前局面的最終得分會是多少?輸入格式 輸入的第一行包含一個正整數T,表示資料的組數。 每組資料輸入有3行,每行有3個整數,用空格分隔,分別表示棋盤每個格子的狀態。0表示格子為空,1表示格子中為“X”,2表示格子中為“O”。保證不會出現其他狀態。 保證輸入的局面合法。(即保證輸入的局面可以通過行棋到達,且保證沒有雙方同時獲勝的情況) 保證輸入的局面輪到Alice行棋。輸出格式 對於每組資料,輸出一行一個整數,表示當前局面的得分。樣例輸入3 1 2 1 2 1 2 0 0 0 2 1 1 0 2 1 0 0 2 0 0 0 0 0 0 0 0 0樣例輸出3 -4 0樣例說明 第一組資料: Alice將棋子放在左下角(或右下角)後,可以到達問題描述中的局面,得分為3。 3為Alice行棋後能到達的局面中得分的最大值。 第二組資料: Bob已經獲勝(如圖),此局面得分為-(3+1)=-4。 第三組資料: 井字棋中若雙方都採用最優策略,遊戲平局,最終得分為0。資料規模和約定 對於所有評測用例,1 ≤ T ≤ 5。 |
題目分析轉載自該部落格, 非常感謝博主分享解題方法。
以下
先說說極大極小演算法,是指給可能出現的所有狀態賦予一個評估值,兩個玩家通過計算不同下棋策略對應不同的評估值,來決定如何下棋。對於井字棋遊戲來說,它的博弈樹(各種走法組合形成的樹)如下:
Alice(MAX)下X,Bob(MIN)下O,直到到達了樹的終止狀態即一位棋手佔領一行,一列、一對角線或所有方格都被填滿。Utility指效用函式,定義遊戲者在狀態S下的數值。在這道題中,就是指:
- 對於Alice已經獲勝的局面,評估得分為(棋盤上的空格子數+1);
- 對於Bob已經獲勝的局面,評估得分為 -(棋盤上的空格子數+1);
- 對於平局的局面,評估得分為0;
所以,在上圖策略樹中,無論當前局勢如何,Alice(MAX)總會選擇最大的評估分對應的走法,Bob(MIN)總會選擇最小的評估分對應的走法。這樣才能使自己儘快的贏得比賽(這一點是關鍵,要想清楚)。題目中只給出了策略樹中葉子節點的評估分的計算方法(贏,輸或平局情況的評估分計算方法),那如何計算策略樹中每個非葉子節點對應的評估分值呢?
答案是採用深度優先搜尋對整個策略樹進行後序遍歷,這樣,先計算策略樹中葉子節點的評估值,在一層層的往上計算非葉子節點的評估值,最終,會得到整個策略樹的評估值,這樣就可以確定玩家在當前情況下應該如何走棋了。
根據以上思路:
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
int map[10], T;
int check()
{
int it = 0;
for (int i = 1; i <= 3; ++i) { // 找出是否可以結束。
if (map[i] == map[i + 3] && map[i + 3] == map[i + 6] && map[i]) {
it = map[i];
break;
}
int k = 3*(i - 1) + 1;
if (map[k] == map[k + 1] && map[k] == map[k + 2] && map[k]) {
it = map[k];
break;
}
}
if (!it) {
if (map[1] == map[5] && map[1] == map[9] && map[1]) it = map[1];
else if (map[3] == map[5] && map[5] == map[7] && map[5]) it = map[5];
}
int cnt = 0;
for (int i = 1; i <= 9; ++i)
if (map[i] == 0) cnt++;
if (it == 0 && cnt == 0) return 0;
if (it == 1) return cnt + 1;
else if (it == 2) return - (cnt + 1);
else return -1;
}
int dfs(int it)
{
int chec = check();
if (chec != -1) return chec;
int ans = it == 1 ? -INF : INF;
for (int i = 1; i <= 9; ++i) {
if (map[i]) continue;
if (it == 1) {
map[i] = 1;
ans = max(ans, dfs(2));
} else {
map[i] = 2;
ans = min(ans, dfs(1));
}
map[i] = 0;
}
return ans;
}
int main()
{
cin >> T;
while (T--) {
for (int i = 1; i <= 9; ++i) {
cin >> map[i];
}
cout << dfs(1) << endl;;
}
}
相關推薦
201803-4棋局評估_極大極小值演算法_對抗搜尋(轉載)
問題描述 試題編號:201803-4 試題名稱:棋局評估 時間限制:1.0s 記憶體限制:256.0MB 問題描述:問題描述 Alice和Bob正在玩井字棋遊戲。 井字棋遊戲的規則很簡單
CCF 201803-4 棋局評估 極大極小搜尋
題意:3X3的井字棋,1先走,2後走,給定一個狀態。當前輪到1走,1,2都按照最優策略行棋,求最後的分數。 #include <cstdio> #include <algorithm
CCF 201803-4 棋局評估 (對抗搜索)
ans clu algo || con mes ccf main using 題意:給一個井字棋的棋盤,對於已經贏的局面,得分是(棋盤上的空格子數+1)*(A為1,B為-1),給出現在的局面求最後的得分 思路:這個叫對抗搜索,每次換一個人搜一下,上次考我還在想下哪裏?結果
201803-4 棋局評估
return 就是 其他 for 切分 namespace mat 序號 ring 這道題當初卡了我不知道多少遍,每次動手想做一下CSP認證的第三道題,都從這道題開始,但每次都被卡住。直接是連題意都有點讀不懂,但是讀懂了之後就會發現,這道題除了特別繁瑣之外,好像也沒用到什麽
201803-4 棋局評估
這道題當初卡了我不知道多少遍,每次動手想做一下CSP認證的第三道題,都從這道題開始,但每次都被卡住。直接是連題意都有點讀不懂,但是讀懂了之後就會發現,這道題除了特別繁瑣之外,好像也沒用到什麼很難的演算法。 借鑑了這位大佬的思路:https://blog.csdn.net/xbb224007/article/
CCF 201803-4 棋局評估
博弈論之前還沒學到。。。 不會啊這題 #include<bits/stdc++.h> using namespace std; int mp[3][3]; bool hang(int i,int f){ return mp[i][0]==f&
ccf csf 201803-4 棋局評估
import java.util.ArrayList; import java.util.List; import java.util.Scanner; class Main { static int num = 0; static int[][] qp;
201803-4 棋局評估 ccf
問題描述 Alice和Bob正在玩井字棋遊戲。 井字棋遊戲的規則很簡單:兩人輪流往3*3的棋盤中放棋子,Alice放的是“X”,Bob放的是“O”,Alice執先。當同一種棋子佔據一行、一列或一條對角線的三個格子時,遊戲結束,該種棋子的持有者獲勝。當
201803-4 棋局評估(動態規劃+優先佇列)
試題編號: 201803-4 試題名稱: 棋局評估 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問題描述 Alice和Bob正在玩井字棋遊戲。 井字棋遊戲的規則很簡單:兩人輪流往3
CCF-CSP-201803-4 棋局評估
問題描述 試題編號: 201803-4 試題名稱: 棋局評估 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問題描述 Alice和Bob正在玩井字棋遊戲。 井字棋遊戲的規則很簡單:
CCF 201803-4 棋局評估(博弈論)
問題描述 試題編號: 201803-4 試題名稱: 棋局評估 時間限制: 1.0s 記憶體限制: 256.0MB
極大極小值搜尋 + 剪枝
/* 題意: Alice和Bob玩遊戲,在一個4x4 的方格上 每個人每次選擇2x2的區域將裡面的四個值求和加到最後的分數當中(兩個人共用一個分數), 然後逆時針翻轉它們, Alice想要分數儘量大Bob想要分數儘量小 兩個人每次的選擇都是最優的,求最後的分數
牛頓法求極大極小值
牛頓法至少有兩個應用方向,1、求方程的根,2、最優化。牛頓法涉及到方程求導,下面的討論均是在連續可微的前提下討論。 1、求解方程。 並不是所有的方程都有求根公式,或者求根公式很複雜,導致求解困難。利用牛頓法,可以迭代求解。 原理是利用泰勒公式,在x0處展開,且展開
中國象棋人機對弈搜尋演算法學習-極大極小值,負極大值,alpha-beta演算法
極大極小值法 深度搜索(dfs)虛擬碼 /** 1。 p 為棋盤 2。 d 為規定的搜素最大深度,比如d層紅方,d-1層為黑方,d-2層為紅方...依此類推,可採用mod2來判斷當前是哪一方 4。評估棋盤的函式evaluation,當然需要看
五子棋(人機)-極大極小值搜尋演算法
從人落子開始到出現勝負或者和局,之間所落的子,構成了一個解。而解空間就是一個樹,解就是這解空間中的一條路徑。只不過這個解空間是電腦的選擇和人的選擇共同構成的(奇數層是電腦(因為輪到電腦落子麼),偶數層是人)。 極大極小值搜尋演算法,來搜尋(回溯)這個解空間:它假設人和電腦都
QT五子棋專案詳解之四:AI人機對戰max-min極大極小值博弈演算法
不考慮博弈的演算法怎麼能算是AI呢?max-min極大極小值演算法就是考慮了博弈的演算法。來看一個簡單的例子在這個棋局中,電腦為白旗,白旗走哪一步更好呢,也許使用策略表會告訴你,應該衝4,但是衝4後,玩家就會連成4。這就是考慮了博弈之後,這一步棋就是敗局。這就是為什麼有max
梯度爆炸與梯度消失的原因以及解決方法,區域性極小值問題以及學習率問題(對SGD的改進)
梯度爆炸與梯度消失的原因:簡單地說,根據鏈式法則,如果每一層神經元對上一層的輸出的偏導乘上權重結果都小於1的話( ),那麼即使這個結果是0.99,在經過足夠多層傳播之後,誤差對輸入層的偏導會趨於0( )。下面是數學推導推導。假設網路輸出層中的第 個神經元輸出為,而要學習的目標
極大極小搜索思想+(α/β)減枝 【轉自-----https://blog.csdn.net/hzk_cpp/article/details/79275772】
ima 基本 個數 博弈論 數字 這就是 pre -- 繼續 極大極小搜索,即minimax搜索算法,專門用來做博弈論的問題的暴力. 多被稱為對抗搜索算法. 這個搜索算法的基本思想就是分兩層,一層是先手,記為a,還有一層是後手,記為b. 這個搜索是認為這a與b的利益關
極大極小演算法轉
作者:知乎使用者 連結:https://www.zhihu.com/question/27221568/answer/140874499 來源:知乎 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。 先來說極小極大演算法主要應用於什麼樣的遊戲: 1. 零和遊戲(
【LeetCode 913】cat-and-mouse | BFS+記憶化 | 極大極小搜尋+AB剪枝 | CGUZ | H
【難題警告!】 核心:BFS + 記憶化(標程) / 極大極小搜尋 + alpha-beta剪枝(近似解) Difficulty : Hard Discuss (32) ACCEPTED 1,341 SUBMISSIONS 6