1. 程式人生 > >CCF 201803-4 棋局評估(博弈論)

CCF 201803-4 棋局評估(博弈論)

問題描述

試題編號:

201803-4

試題名稱:

棋局評估

時間限制:

1.0s

記憶體限制:

256.0MB

問題描述:

問題描述

  Alice和Bob正在玩井字棋遊戲。
  井字棋遊戲的規則很簡單:兩人輪流往3*3的棋盤中放棋子,Alice放的是“X”,Bob放的是“O”,Alice執先。當同一種棋子佔據一行、一列或一條對角線的三個格子時,遊戲結束,該種棋子的持有者獲勝。當棋盤被填滿的時候,遊戲結束,雙方平手。
  Alice設計了一種對棋局評分的方法:
  - 對於Alice已經獲勝的局面,評估得分為(棋盤上的空格子數+1);
  - 對於Bob已經獲勝的局面,評估得分為 -(棋盤上的空格子數+1);
  - 對於平局的局面,評估得分為0;

http://118.190.20.162/RequireFile.do?fid=yrNHga4H


  例如上圖中的局面,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行棋後能到達的局面中得分的最大值。
  第二組資料:
http://118.190.20.162/RequireFile.do?fid=fEF6hem5

  Bob已經獲勝(如圖),此局面得分為-(3+1)=-4。
  第三組資料:
  井字棋中若雙方都採用最優策略,遊戲平局,最終得分為0。

資料規模和約定

  對於所有評測用例,1 ≤ T ≤ 5。

------------------------------------------------------------

思路

博弈論模板題,遞迴搜尋狀態。

Alice/Bob的每一步都在當前所有可行的行棋位置中選擇可以使場上得分最大/小的位置。

具體而言,就是:

1. dfs(s, who)表示當前狀態為s(三進製表示整個棋盤),行棋者為who(0:Alice, 1:Bob)情況下該行棋者的最大/小得分

2. 若當前Alice行棋,則遍歷s中0的位,將其置為1得到s2, 遞迴計算dfs(s2,1),取諸dfs(s2,1)中的最大值為dfs(s,0)的返回值

3. 若當前Bob行棋,則遍歷s中0的位,將其置為2得到s2, 遞迴計算dfs(s2,0),取諸dfs(s2,0)中的最大值為dfs(s,1)的返回值

4. 當棋局已分出勝負或者棋盤已佔滿但未分勝負時直接返回

注意點:

1. 棋盤全佔滿時也能分出勝負;

2. 如果棋盤全佔滿(無處著棋)且未分勝負,則返回0

------------------------------------------------------------

程式碼

#include<cstdio>
#include<algorithm>

const short seq[8][3] = {{0,4,8},{2,4,6},{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8}};

short myfind(int s, short n)			// s狀態下第n個格子的值 
{
	int i, thr = 1;
	for (i=0; i<n; i++)
	{
		thr *= 3;
	}
	int a = (s/thr)%3;
	return a;
}

short myempty(int s)
{
	int cnt = 0, i, a;
	for (i=0; i<9; i++)
	{
		a = s % 3;
		if (a==0)
		{
			cnt++;
		}
		s /= 3;
	}
	return cnt;
}

short win(int s)					// 根據棋盤狀態判斷是還沒結束/Alice/Bob獲勝(0/-1/1) 
{
	int i, j, a, cnt1 = 0, cnt2 = 0;
	short ans = 0;
	for (i=0; i<8; i++)
	{
		cnt1 = 0;
		cnt2 = 0;
		for (j=0; j<3; j++)
		{
			a = myfind(s, seq[i][j]);
			if (a==1)
			{
				cnt1++;
			}
			else if (a==2)
			{
				cnt2++;
			}
			if (cnt1==3)
			{
				ans = myempty(s);
				return (ans+1);
			}
			else if (cnt2==3)
			{
				ans = myempty(s);
				return -(ans+1);
			}
		}
	}
	return 0;
}

short dfs(int s, bool who)			// s表示棋盤狀態,who(0/1): 輪到Alice/Bob行棋 
{
	short score = win(s);
	if (score != 0)
	{
		return score;
	}
	int i, s1 = s, s2, a, thr = 1;
	short mymax = -10, mymin = 10;
	if (!who)										// Alice行棋 
	{
		for (i=0; i<9; i++)
		{
			a = s1 % 3;
			s1 /= 3;
			if (a == 0)
			{
				s2 = s + 1 * thr;
				mymax = std::max(dfs(s2, 1), mymax);
			}
			thr *= 3;
		}
		if (mymax == -10)
		{
			return 0;
		}
		else
		{
			return mymax;
		}
	}
	else 											// Bob行棋 
	{
		for (i=0; i<9; i++)
		{
			a = s1 % 3;
			s1 /= 3;
			if (a == 0)
			{
				s2 = s + 2 * thr;
				mymin = std::min(dfs(s2, 0), mymin);
			}
			thr *= 3;
		}
		if (mymin == 10)
		{
			return 0;
		}
		else
		{
			return mymin;
		}
	}
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("CCF201803-4.txt", "r", stdin);
	#endif 
	int t, a, i, s, thr;			// s: 三進製表示棋盤狀態 
	scanf("%d", &t);
	while (t--)
	{
		s = 0;
		thr = 1;
		for (i=0; i<9; i++)
		{
			scanf("%d", &a);
			s += thr * a;
			thr *= 3;
		}
		printf("%d\n", dfs(s, 0));
	}
	return 0;
}

相關推薦

CCF 201803-4 棋局評估博弈論

問題描述 試題編號: 201803-4 試題名稱: 棋局評估 時間限制: 1.0s 記憶體限制: 256.0MB

CCF 201803-4 棋局評估 對抗搜索

ans clu algo || con mes ccf main using 題意:給一個井字棋的棋盤,對於已經贏的局面,得分是(棋盤上的空格子數+1)*(A為1,B為-1),給出現在的局面求最後的得分 思路:這個叫對抗搜索,每次換一個人搜一下,上次考我還在想下哪裏?結果

201803-4 棋局評估動態規劃+優先佇列

試題編號: 201803-4 試題名稱: 棋局評估 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問題描述   Alice和Bob正在玩井字棋遊戲。   井字棋遊戲的規則很簡單:兩人輪流往3

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 201803-4 棋局評估 極大極小搜尋

題意:3X3的井字棋,1先走,2後走,給定一個狀態。當前輪到1走,1,2都按照最優策略行棋,求最後的分數。 #include <cstdio> #include <algorithm

201803-4棋局評估_極大極小值演算法_對抗搜尋轉載

問題描述 試題編號:201803-4 試題名稱:棋局評估 時間限制:1.0s 記憶體限制:256.0MB 問題描述:問題描述  Alice和Bob正在玩井字棋遊戲。   井字棋遊戲的規則很簡單

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執先。當同一種棋子佔據一行、一列或一條對角線的三個格子時,遊戲結束,該種棋子的持有者獲勝。當

CCF-CSP-201803-4 棋局評估

問題描述 試題編號: 201803-4 試題名稱: 棋局評估 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問題描述   Alice和Bob正在玩井字棋遊戲。   井字棋遊戲的規則很簡單:

201803-4 棋局評估

return 就是 其他 for 切分 namespace mat 序號 ring 這道題當初卡了我不知道多少遍,每次動手想做一下CSP認證的第三道題,都從這道題開始,但每次都被卡住。直接是連題意都有點讀不懂,但是讀懂了之後就會發現,這道題除了特別繁瑣之外,好像也沒用到什麽

201803-4 棋局評估

這道題當初卡了我不知道多少遍,每次動手想做一下CSP認證的第三道題,都從這道題開始,但每次都被卡住。直接是連題意都有點讀不懂,但是讀懂了之後就會發現,這道題除了特別繁瑣之外,好像也沒用到什麼很難的演算法。 借鑑了這位大佬的思路:https://blog.csdn.net/xbb224007/article/

CCF 201712-4 行車路線 spfa

問題描述 小明和小芳出去鄉村玩,小明負責開車,小芳來導航。 小芳將可能的道路分為大道和小道。大道比較好走,每走 1 公里小明會增加 1 的疲勞度。小道不好走,如果連續走小道,小明的疲勞

CCF 201803-4棋局評估對抗搜尋

思路 ①當Alice下的時候,我們嘗試所有可能的下法,並找到所有下法中使結果最大的一個 當Bob下的時候,我們嘗試所有可能的下法,並找到所有下法中使結果最小的一個 ②輪流執子,直到雙方有人勝利或棋盤填滿  蒟蒻我還是不能很好的表達出意思來...QAQ C++滿分

CCF-CSP201609-4 交通規劃Dijkstra+優先佇列

題目連結 問題描述 試題編號: 201609-4 試題名稱: 交通規劃 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問題描述   G國國王來中國參觀後,被中國的高速鐵路深深的震撼,決定為自己

CCF 201509-4】高速公路強連通分量

題目抽象 求有多少個結點對能夠互相到達 大致思路 思路一【50分】:對每個結點DFS,求傳遞閉包,時間為O(V*E),程式碼簡單,但是超時 思路二【100分】:計算圖的強連通分量(SCC),各個分量裡面的點都是可以相互到達的 SCC演算法:O(V+E)

CCF 201609-4 交通規劃 迪傑斯特拉+優先佇列

這道題我沒有好的思路,剛開始用的是spfa打的,結果不行。 之前沒見過迪傑斯特拉+佇列優化。 但這確實挺好用,。要是最小生成樹跟最短路結合起來的話用這個跑最好不過了。 所以對這道題非常適用。 #include<bits/stdc++.h> using n

CCF 201712-4 行車路線100分

宣告:CCF提交後得100分,但程式存在bug,過段時間修改 試題編號: 201712-4 試題名稱: 行車路線 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問題描述   小明和小芳出去鄉村玩

ccf 201803-3 URL對映100分

問題描述   URL 對映是諸如 Django、Ruby on Rails 等網頁框架 (web frameworks) 的一個重要元件。對於從瀏覽器發來的 HTTP 請求,URL 對映模組會解析請求中的 URL 地址,並將其分派給相應的處理程式碼。現在,請你

CCF 201803-3 URL對映字串模擬

  URL 對映是諸如 Django、Ruby on Rails 等網頁框架 (web frameworks) 的一個重要元件。對於從瀏覽器發來的 HTTP 請求,URL 對映模組會解析請求中的 URL 地址,並將其分派給相應的處理程式碼。現在,請你來實現一個簡單的 URL 對映功能。  本題中 URL 對映

SRM div1 MagicNim博弈論

col 保持 clu blog stream ant 現在 ios 個數 題目大意: 給出n+1堆石子,前n堆石子的數量是a[i],最後一堆只有1個石子,但是具有魔力 拿走該石子的一方可以選擇接下來是進行普通的Nim遊戲還是anti-nim遊戲 問是先手必勝還是必敗 首