ACM-ICPC 2018 徐州赛区网络预赛 B-BE, GE or NE
题意:两个人做游戏起初有m积分,A先走B后走,每次有三种选择a,b,c,每次+a但是要<=100,-b但要>=-100,c取反,>=给定的k会有GE,<=会有BE,两者之间NE,A想要GE,B是BE,都不是就NE.
思路: 因为要满足GE,分数越高越好,而要满足BE,分数越低越好,因此A的策略应当是取尽可能大的,B的策略应当是取尽可能小的。此时我们不妨用dp去解决。
我们设dp[i][j]表示在第i个关卡中,分数为j分时所能获得的最大的分数。而因为会有abc三种选项的状态转移,则对于三个状态分别有
而对于i为奇数情况下是A选,则i的状态要优先选最大值;而对于i为偶数的情况下B选,则优先选最小。
而需要注意的是,因为j的值可能为负数,因此我们可以用map(常数较大)或者直接将j+100去从n倒着dp.
#include <bits/stdc++.h> #define maxn 1005 using namespace std; int dp[maxn][205]; int a[maxn], b[maxn], c[maxn]; const int bit = 100; int main() { int n, m, k, l; scanf("%d%d%d%d", &n, &m, &k, &l); for (int i = 1; i <= n; i++) { scanf("%d%d%d", &a[i], &b[i], &c[i]); } for (int i = -100; i <= 100; i++) { dp[n + 1][i + bit] = i; } for (int i = n; i >= 1; i--) { for (int j = -100; j <= 100; j++) { int o1 = dp[i + 1][min(j + a[i], 100) + bit]; int o2 = dp[i + 1][max(j - b[i], -100) + bit]; int o3 = dp[i + 1][-j + bit]; if (i & 1) { dp[i][j + bit] = -100; if (a[i]) dp[i][j + bit] = max(dp[i][j + bit], o1); //状态转移 if (b[i]) dp[i][j + bit] = max(dp[i][j + bit], o2); if (c[i]) dp[i][j + bit] = max(dp[i][j + bit], o3); } else { dp[i][j + bit] = 100; if (a[i]) dp[i][j + bit] = min(dp[i][j + bit], o1); if (b[i]) dp[i][j + bit] = min(dp[i][j + bit], o2); if (c[i]) dp[i][j + bit] = min(dp[i][j + bit], o3); } } } if (dp[1][m + bit] >= k) puts("Good Ending"); else if (dp[1][m + bit] <= l) puts("Bad Ending"); else puts("Normal Ending"); return 0; }
.