Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

折腾了很久,模仿一个老外写的,莫名其妙A的,我自己都不是很理解怎么就A了,放个代码

Posted by zoujing1978 at 2018-10-20 11:03:22 on Problem 2633 and last updated at 2018-10-20 16:28:21
/*
题意:星球大战游戏,Nils 和 Mikael两玩家,Nils先手。 X大小的星球,K种缩小武器。
给出缩小武器 i 的值 f[i] ,使用后星球大小变为X*f[i]。首先将星球大小变为小于等于1的一方获胜,求获胜方。
*/

// 功能:求解POJ2633
// 作者:邹竞
// 单位:湖南涉外经济学院计算机系
// 版本:v2.0(前一个版本超时)
// 日期:2018-10-20

#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cfloat>
using namespace std;

struct Node				// 博弈过程中的状态结点类型
{
	int dep;			// 结点深度
	double x;			// 星球当前状态下的体积
	int turn;			// 轮到哪一方做决策
};

class FunnyGames
{
protected:
	int k;				// k种武器
	double* f;			// f[i]表示第i种武器能把星球缩小百分之多少
	double x;			// x表示星球最初的体积
	vector<Node> v;		// v顺序存放博弈过程中生成的结点,注意:在v中,每个结点的x值是降序的
	unsigned int* flag;	// flag[i]表示上一次使用第i种武器生成的结点存放在向量v下标为多少的位置
	int Game();			// 某个测试用例的博弈过程
public:
	void Solve();
};

int FunnyGames::Game()
{
	v.clear();
	v.reserve(50000);
	// 构造初始状态
	Node state;
	state.x = x;
	state.turn = 0;
	state.dep = 0;
	v.push_back(state);
	int start = 0;
	flag = new unsigned int[k];
	fill(flag, flag + k, 0);

	//printf("<%f,%d,%d>\n", v[0].x, v[0].turn, v[0].dep);

	// v[start]表示某一回合最终做出的决策对应的结点
	while (v[start].x > 1)
	{
		double max = DBL_MIN;
		double min = DBL_MAX;
		int dep = -1;
		int p = -1;
		// 考虑每一种策略f[i]
		for (int i = 0; i < k; i++)
		{
			// 如果博弈过程已经生成的某个状态,应用了策略f[i]后,星球体积还没有上一回合的星球体积小,则不能将策略f[i]应用于该状态,而是应该寻找另一个能应用该策略的状态
			while (flag[i] < v.size() && v[flag[i]].x * f[i] >= v[start].x)
			{
				flag[i]++;
			}

			// 代码能走到这里说明策略f[i]可以应用于状态v[flag[i]]
			if (v[flag[i]].turn == 0 && min > v[flag[i]].x * f[i])		// 如果应用策略的结点轮到先手执行策略,应该在所有的策略及应用策略的结点中,找到使某结点应用某策略后星球体积变得最小的值
			{
				min = v[flag[i]].x * f[i];
				dep = v[flag[i]].dep + 1;
				p = i;
			}
			else if (v[flag[i]].turn == 1 && max < v[flag[i]].x * f[i])	// 如果应用策略的结点轮到后手执行策略,应该在所有的策略及应用策略的结点中,找到使某结点应用某策略后星球体积变得最大的值
			{
				max = v[flag[i]].x * f[i];
				dep = v[flag[i]].dep + 1;
				p = i;
			}

			//printf("flag[%d]=%d, ", i, flag[i]);

		}

		//printf("\np=%d\n",p);

		if (min < DBL_MAX)	// 如果轮到先手执行策略,
		{
			// 生成下一个状态结点(注意父节点不是v[start]而是某个v[flag[i]]),星球体积变成min,接下来轮到后手做决策,将新的状态节点添加到v中
			state.x = min;
			state.turn = 1;
			state.dep = dep;
			start++;
			v.push_back(state);

			//for (int i = 0; i < start + 1; i++)
			//{
			//	printf("<%f,%d,%d> ", v[i].x, v[i].turn, v[i].dep);
			//}
			//printf("\n");

			// 如果上一个结点也是先手完决策生成的结点,这一次先手做了一个使得星球体积变得更小的决策,则上一次的决策无意义,可以用当前结点替换上一个结点
			if (v[start - 1].turn == 1)
			{
				v[start - 1].x = v[start].x;
				v[start - 1].dep = v[start].dep;
				v.erase(v.end() - 1);
				start--;

				//for (int i = 0; i < start + 1; i++)
				//{
				//	printf("<%f,%d,%d> ", v[i].x, v[i].turn, v[i].dep);
				//}
				//printf("\n");

			}

			//printf("min=%f\n\n", min);

		}
		else				// 如果轮到后手执行策略
		{
			// 生成下一个状态结点(注意父节点不是v[start]而是某个v[flag[i]]),星球体积变成max,轮到先手做决策,将新的状态节点添加到v中
			state.x = max;
			state.turn = 0;
			state.dep = dep;
			start++;
			v.push_back(state);

			//for (int i = 0; i < start + 1; i++)
			//{
			//	printf("<%f,%d,%d> ", v[i].x, v[i].turn, v[i].dep);
			//}
			//printf("\n");

			// 如果上一个结点也是后手做完决策之后生成的,这一次后手做了一个使得星球体积变得没那么小的决策,则上一次的决策无意义,可以用当前结点替换上一个结点
			if (v[start - 1].turn == 0)
			{
				v[start - 1].x = v[start].x;
				v[start - 1].dep = v[start].dep;
				v.erase(v.end() - 1);
				start--;

				//for (int i = 0; i < start + 1; i++)
				//{
				//	printf("<%f,%d,%d> ", v[i].x, v[i].turn, v[i].dep);
				//}
				//printf("\n");

			}

			//printf("max=%f\n\n", max);

		}
	}
	while (v[start - 1].x < 1)
	{
		start--;
	}
	delete[] flag;
	return v[start].turn;
}

void FunnyGames::Solve()
{
	int t = 0;
	scanf("%d", &t);
	for (int i = 0; i < t; i++)
	{
		scanf("%lf %d", &x, &k);
		f = new double[k];
		for (int j = 0; j < k; j++)
		{
			scanf("%lf", &f[j]);
		}
		if (Game() == 0)
		{
			printf("Mikael\n");
		}
		else
		{
			printf("Nils\n");
		}
		delete[] f;
	}
}

int main()
{
	FunnyGames obj;
	obj.Solve();
	return 0;
}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator