| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
折腾了很久,模仿一个老外写的,莫名其妙A的,我自己都不是很理解怎么就A了,放个代码/*
题意:星球大战游戏,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: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator