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