1. 程式人生 > >CCF 棋局評估

CCF 棋局評估

問題描述

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

問題描述

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


  - 對於平局的局面,評估得分為0; 例如上圖中的局面,Alice已經獲勝,同時棋盤上有2個空格,所以局面得分為2 + 1 = 3.由於Alice並不喜歡計算,所以他請教擅長程式設計的你,如果兩人都以最優策略行棋,那麼當前局面的最終得分會是多少


 

輸入格式

  輸入的第一行包含一個正整數T,表示資料的組數。
  每組資料輸入有3行,每行有3個整數,用空格分隔,分別表示棋盤每個格子的狀態.0表示格子為空,1表示格子中為“X”,2表示格子中為“O”。保證不會出現其他狀態。
  保證輸入的局面合法。(即保證輸入的局面可以通過行棋到達,且保證沒有雙方同時獲勝的情況),
  保證輸入的局面輪到愛麗絲行棋。

輸出格式

  對於每組資料,輸出一行一個整數,表示當前局面的得分。

樣例輸入

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

樣例說明

  第一組資料:
  艾麗斯將棋子放在左下角(或右下角)後,可以到達問題描述中的局面,得分為3
  .3為愛麗絲棋行後能到達的局面中得分的最大值
  第二組資料:Bob已經獲勝(如圖),此局面得分為 - (3 + 1)= - 4.第三組資料:井字棋中若雙方都採用最優策略,遊戲平局,最終得分為0 。



 

資料規模和約定

  對於所有評測用例,1≤ 

Ť  ≤5。

50分的程式碼......不知道怎麼改進

我的想法是,每次進入DFS是判斷當前局勢是否可以結束遊戲,可以則優化微型和馬克西,如不能,則進行此次的最優下法,方法如下:判斷是否有哪一步可以讓自己獲勝,如沒有,則判斷是否接下來一步對手能獲勝,有的話則封堵他,如進入這兩個判斷語句,則執行都回,因為是最優解,必須執行,如果都不滿足,則遍歷剩餘0

#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#define MAX_SIZE 1005
#define INF 10
using namespace std;

int matrix[4][4];
int n, node_i, node_j;
int mini = INF, maxi = -INF;
int nextItem(int index)
{
	return index == 1 ? 2 : 1;
}
bool check_x_y(int index)
{
	int num[3] = {0}, loc = 0;
	for (int j = 1; j <= 3; j++)
	{
		//判斷行
		num[0] = num[1] = num[2] = 0;
		loc = 0;
		switch (matrix[j][1])
		{
		case 0:
			loc = 1;
			num[0]++;
			break;
		case 1:
			num[1]++;
			break;
		case 2:
			num[2]++;
			break;
		}
		switch (matrix[j][2])
		{
		case 0:
			loc = 2;
			num[0]++;
			break;
		case 1:
			num[1]++;
			break;
		case 2:
			num[2]++;
			break;
		}
		switch (matrix[j][3])
		{
		case 0:
			loc = 3;
			num[0]++;
			break;
		case 1:
			num[1]++;
			break;
		case 2:
			num[2]++;
			break;
		}
		if (num[0] == 1)
		{
			if (num[index] == 2)
			{
				node_i = j;
				node_j = loc;
				return 1;
			}
		}
		//判斷列
		num[0] = num[1] = num[2] = 0;
		loc = 0;
		switch (matrix[1][j])
		{
		case 0:
			loc = 1;
			num[0]++;
			break;
		case 1:
			num[1]++;
			break;
		case 2:
			num[2]++;
			break;
		}
		switch (matrix[2][j])
		{
		case 0:
			loc = 2;
			num[0]++;
			break;
		case 1:
			num[1]++;
			break;
		case 2:
			num[2]++;
			break;
		}
		switch (matrix[3][j])
		{
		case 0:
			loc = 3;
			num[0]++;
			break;
		case 1:
			num[1]++;
			break;
		case 2:
			num[2]++;
			break;
		}
		if (num[0] == 1)
		{
			if (num[index] == 2)
			{
				node_i = loc;
				node_j = j;
				return 1;
			}
		}
	}
	//判斷正斜
	num[0] = num[1] = num[2] = 0;
	loc = 0;
	switch (matrix[1][1])
	{
	case 0:
		loc = 1;
		num[0]++;
		break;
	case 1:
		num[1]++;
		break;
	case 2:
		num[2]++;
		break;
	}
	switch (matrix[2][2])
	{
	case 0:
		loc = 2;
		num[0]++;
		break;
	case 1:
		num[1]++;
		break;
	case 2:
		num[2]++;
		break;
	}
	switch (matrix[3][3])
	{
	case 0:
		loc = 3;
		num[0]++;
		break;
	case 1:
		num[1]++;
		break;
	case 2:
		num[2]++;
		break;
	}
	if (num[0] == 1)
	{
		if (num[index] == 2)
		{
			node_i = loc;
			node_j = loc;
			return 1;
		}
	}
	//判斷反斜
	num[0] = num[1] = num[2] = 0;
	loc = 0;
	switch (matrix[1][3])
	{
	case 0:
		loc = 1;
		num[0]++;
		break;
	case 1:
		num[1]++;
		break;
	case 2:
		num[2]++;
		break;
	}
	switch (matrix[2][2])
	{
	case 0:
		loc = 2;
		num[0]++;
		break;
	case 1:
		num[1]++;
		break;
	case 2:
		num[2]++;
		break;
	}
	switch (matrix[3][1])
	{
	case 0:
		loc = 3;
		num[0]++;
		break;
	case 1:
		num[1]++;
		break;
	case 2:
		num[2]++;
		break;
	}
	if (num[0] == 1)
	{
		if (num[index] == 2)
		{
			node_i = loc;
			node_j = 4 - loc;
			return 1;
		}
	}
	return 0;
}
int getWhite()
{
	int num = 0;
	for (int i = 1; i <= 3; i++)
	{
		for (int j = 1; j <= 3; j++)
		{
			if (matrix[i][j] == 0)
			{
				num++;
			}
		}
	}
	return num;
}
int win()
{
	for (int i = 1; i <= 3; i++)
	{
		if (matrix[i][1] == matrix[i][2] && matrix[i][2] == matrix[i][3] && matrix[i][2] != 0)
		{
			return matrix[i][2];
		}
		if (matrix[1][i] == matrix[2][i] && matrix[2][i] == matrix[3][i] && matrix[2][i] != 0)
		{
			return matrix[2][i];
		}
	}
	if (matrix[1][1] == matrix[2][2] && matrix[2][2] == matrix[3][3] && matrix[2][2] != 0)
	{
		return matrix[2][2];
	}
	if (matrix[1][3] == matrix[2][2] && matrix[2][2] == matrix[3][1] && matrix[2][2] != 0)
	{
		return matrix[2][2];
	}
	return 0;
}
bool checkGameOver()
{
	int white = getWhite(), res = win();
	if (res != 0)
	{
		if (res == 1)
		{
			// cout << "本次遊戲結束. 1 勝利,空白個數:" << white << endl;
			maxi = max(maxi, white + 1);
		}
		else
		{
			// cout << "本次遊戲結束. 2 勝利,空白個數:" << white << endl;
			mini = min(mini, -white - 1);
		}
		// for (int i = 1; i <= 3; i++)
		// {
		// 	for (int j = 1; j <= 3; j++)
		// 	{
		// 		cout << matrix[i][j];
		// 	}
		// 	cout << endl;
		// }
		return true;
	}
	return false;
}
void dfs(int index)
{
	//判斷是否結束
	if (checkGameOver())
	{
		return;
	}
	//檢測能否有讓自己勝利的步局
	if (check_x_y(index) == 1)
	{
		// cout << index << "發現可勝利位置,落子在(" << node_i << "," << node_j << ")" << endl;
		int a = node_i, b = node_j;
		matrix[a][b] = index;
		dfs(nextItem(index));
		matrix[a][b] = 0;
		return;
	}
	//檢測能否有讓對手下一步勝利的步局
	if (check_x_y(nextItem(index)) == 1)
	{
		// cout << index << "發現對手有可勝位置,落子在(" << node_i << "," << node_j << ")" << endl;
		int a = node_i, b = node_j;
		matrix[a][b] = index;
		dfs(nextItem(index));
		matrix[a][b] = 0;
		return;
	}
	// 遍歷空白
	for (int i = 1; i <= 3; i++)
	{
		for (int j = 1; j <= 3; j++)
		{
			if (matrix[i][j] == 0)
			{
				// cout << index << "落子在(" << i << "," << j << ")" << endl;
				matrix[i][j] = index;
				dfs(nextItem(index));
				matrix[i][j] = 0;
			}
		}
	}
}
int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);

	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		mini = INF, maxi = -INF;
		for (int j = 1; j <= 3; j++)
		{
			cin >> matrix[j][1] >> matrix[j][2] >> matrix[j][3];
		}
		//判斷空
		bool nullFlag = true;
		for (int j = 1; j <= 3; j++)
		{
			if (matrix[j][1] != 0 || matrix[j][2] != 0 || matrix[j][3] != 0)
			{
				nullFlag = false;
				break;
			}
		}
		if (nullFlag)
		{
			cout << 0 << endl;
			continue;
		}
		//dfs
		dfs(1);
		if (maxi != -INF)
		{
			cout << maxi << endl;
		}
		else if (mini != INF)
		{
			cout << mini << endl;
		}
		else
		{
			cout << 0 << endl;
		}
	}
	return 0;
}