OR58. 取石子游戏
描述
今天,Alice 和 Bob 两个人发明了一个新的取石子游戏。我们将 n 枚石子摆放成一行,从左到右每枚石子有两个参数,能量ei 和得分ai 。Alice 和 Bob 两人轮流决策,从左到右依次取石子,Alice 先手。每个回合,玩家可以选择下列两个操作之一:1. 消耗一个单位的能量,跳过这个回合。2. 取当前位置的石子。初始时,两个玩家分别有A和B单位的能量,两个玩家的目的都是最大化自己的得分,双方都采取最优决策,问游戏结束时,Alice 和 Bob 的得分分别为多少。
题目给定A和B(0≤A≤10^9,0≤B≤10^9)同时给定石子个数n(1≤n≤100),每颗石子的能量e和得分a(所有数字均为正整数,e中元素均小于等于10^9)。请返回一个数组,其中第一个元素为Alice的得分,第二个元素为Bob的得分。
9,0,7,[66,2,6,2,8,4,3],[7,12,65,7,4,40,15]
返回:[112,38]
C++ 解法, 执行用时: 1ms, 内存消耗: 624KB, 提交时间: 2017-10-15
//这题太难,能理解对照着写出来就好了 class Stones { public: vector<int> result(int A, int B, int n, vector<int> e, vector<int> a) { // write code here for(int i=0; i<=n; ++i) fill(dp[i], dp[i]+200, INF); dp[n][0] = -INF; int sum = 0; for(int i=n-1; i>=0; --i) { sum += a[i]; for(int j=0; j<=sum; ++j) { dp[i][j] = min(max(1LL, dp[i+1][j]+e[i]+1), -(dp[i+1][sum-j+1]-1)-e[i]); } } int res = 0; for(int j=sum; j>0; --j) if(A-B >= dp[0][j]) { res = j; break; } vector<int> ans(2); ans[0] = res, ans[1] = sum-res; return ans; } private: static const long long INF; static const int MAXN = 203; long long dp[MAXN][200]; }; const long long Stones::INF = 0x1fffffffffffffff;
C++ 解法, 执行用时: 1ms, 内存消耗: 676KB, 提交时间: 2017-06-12
//智商欠费,实在搞不懂 class Stones { public: vector<int> result(int A, int B, int n, vector<int> e, vector<int> a) { // write code here const long long inf = 0x3f3f3f3f3f3f3f3f; vector<vector<long long>>dp(n + 1, vector<long long>(200, inf)); int sum = 0, ans; dp[n][0] = -inf; for (int i = n - 1; i >= 0; i--){ sum += a[i]; for (int j = 0; j <= sum; j++){ long long Achoose = -(dp[i + 1][sum - j + 1] - 1) - e[i]; long long Apass = max(1ll, dp[i + 1][j] + (e[i] + 1)); dp[i][j] = min(Achoose, Apass); if (i == 0 && dp[i][j] <= A - B) ans = j; } } return vector<int>{ans, sum - ans}; } };