Advertisement

201803-4 棋局评估(动态规划+优先队列)

阅读量:
试题编号: 201803-4
试题名称: 棋局评估
时间限制: 1.0s
内存限制: 256.0MB

Alice与Bob正在进行一场井字棋比赛。

例如上图所示的局面,在该情况下Alice已经取得了胜利,并且棋盘上剩余有两个空格位置。因此这一局面的总得分为2加1等于3分。

Bob已经取得胜利(如图),此状态下得分为-(3+1)=-4。 第三组测试数据:井字棋中若双方都采取最优策略,则达到平衡状态, 其结果为零分。 在所有评测用例中, 1 ≤ T ≤ 5.

为每一种棋局建立独特的标识以便于实施动态规划...原样保留),根据不同的玩家需求,在各玩家之间采用重载优化的优先队列策略来满足各自的目标要求(其中Alice追求最高评分而Bob则寻求最低评分)。

复制代码
  
    
 #include <map>  
    
 #include <cmath>  
    
 #include <queue>  
    
 #include <cstdio>  
    
 #include <string>  
    
 #include <cstring>  
    
 #include <iostream>  
    
 #include <algorithm> 
    
 #include <sstream> 
    
 #include <time.h> 
    
 #include <vector>
    
 #include <list>
    
  
    
 using namespace std;
    
 //201803-4  棋局评估
    
 struct Chess {
    
 	int num[3][3];	//当前局势
    
 	int Sum;		//局势的唯一标识
    
 	bool flag;		//表示该由谁下子
    
 	int score;		//得分
    
 };
    
 map<int, Chess>Array;	//存放算出分数的局势
    
  
    
 struct My_int {
    
 	int score;
    
 	bool Flag;
    
 	bool operator <(const My_int& s)const
    
 	{
    
 		if (Flag == 1)
    
 			return score > s.score;		//最小堆
    
 		else
    
 			return score < s.score;			//最大堆
    
 	}
    
 };
    
 void Get_Num(Chess &D)
    
 {
    
 	int Sum = 0;
    
 	for (int i = 0; i < 3; i++)
    
 	{
    
 		for (int j = 0; j < 3; j++)
    
 		{
    
 			cin >> D.num[i][j];
    
 			Sum += D.num[i][j] * pow(3, i * 3 + j);
    
 		}
    
 	}
    
 	D.flag = 0;		//该由Alice放X
    
 	D.Sum = Sum;
    
 }
    
 bool Judge(int num[3][3], int &p)
    
 {
    
 	int Zreo_Num = 0;
    
 	int ff = 0;
    
 	for (int i = 0; i < 3; i++)
    
 	{
    
 		for (int j = 0; j < 3; j++)
    
 		{
    
 			if (num[i][j] == 0)
    
 				Zreo_Num++;
    
 		}
    
 	}
    
 	for (int i = 0; i < 3; i++)
    
 	{
    
 		if (num[i][i] != 0)
    
 		{
    
 			if ((num[i][0] == num[i][1] && num[i][1] == num[i][2]) || (num[0][i] == num[1][i] && num[1][i] == num[2][i]))
    
 			{
    
 				ff = num[i][i]; break;
    
 			}
    
 			else if (i == 1 && ((num[0][0] == num[1][1] && num[1][1] == num[2][2]) || (num[0][2] == num[1][1] && num[1][1] == num[2][0])))
    
 			{
    
 				ff = num[i][i]; break;
    
 			}
    
 		}
    
 	}
    
 	if (ff == 0 && Zreo_Num == 0)	//棋局已满且没有胜出方
    
 	{
    
 		p = 0; return 1;		//平局,结束
    
 	}
    
 	else if (ff == 1)	//Alice胜出
    
 	{
    
 		p = Zreo_Num + 1; return 1;	//结束
    
 	}
    
 	else if (ff == 2)	//Bob胜出
    
 	{
    
 		p = -Zreo_Num - 1; return 1;	//结束
    
 	}
    
 	else
    
 		return 0;	//游戏没结束
    
 }
    
 int Find_Score(Chess D)
    
 {
    
 	if (Array.find(D.Sum) == Array.end())	//表示还没有计算过这种局势的分数
    
 	{
    
 		int p;
    
 		if (bool F = Judge(D.num, p))		//已经分出胜负
    
 			return p;
    
 		priority_queue<My_int> S;
    
 		for (int i = 0; i < 3; i++)
    
 		{
    
 			for (int j = 0; j < 3; j++)
    
 			{
    
 				if (D.num[i][j] == 0)
    
 				{
    
 					Chess Save = D;
    
 					Save.num[i][j] = 1 + D.flag;
    
 					Save.Sum += Save.num[i][j]*pow(3, i * 3 + j);
    
 					Save.flag = !D.flag;	//更改下子的人
    
 					My_int s;
    
 					s.score = Find_Score(Save);
    
 					s.Flag = D.flag;
    
 					S.push(s);
    
 				}
    
 			}
    
 		}
    
 		D.score = S.top().score;
    
 		Array[D.Sum] = D;		//保存当前局势结果进入数组
    
 		return D.score;		//返回最优
    
 	}
    
 	else
    
 		return Array[D.Sum].score;
    
 }
    
 int main()
    
 {
    
 	int i, j, N, M;
    
 	Chess Data;
    
 	cin >> N;
    
  
    
 	//int mm = Find_Score(Data);
    
  
    
 	for (i = 0; i < N; i++)
    
 	{
    
 		Get_Num(Data);
    
 		M = Find_Score(Data);
    
 		cout << M << endl;
    
 	}
    
  
    
 	cin >> N;
    
 	return 0;
    
 }

全部评论 (0)

还没有任何评论哟~