1. 程式人生 > >201803-4棋局評估_極大極小值演算法_對抗搜尋(轉載)

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