ACM-ICPC 2018 徐州赛区网络预赛 B-BE, GE or NE

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;
}
View Code

.

原文地址:https://www.cnblogs.com/kuroko-ghh/p/9630017.html