Codeforces Round #380 Div.2 F - Financiers Game

F - Financiers Game

这种两人博弈一般都可以用两个dp写, 一个dp描述第一个人的最优态, 第二个dp描述第二个人的最优态,难点在于优化空间。。。

我感觉这个空间开得有点玄学。。

dp[ op ][ l ] [ d ] [ k ] 表示到第op个人先手,在第任意轮的时候第一个人和第二个人取的个数只差不会超过180,所以用他们的差值开一维状态。

d = (l - 1) - (n - r), 只有区间 (l , n + d - l - 1)的情况下的最优值。

 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 #define mk make_pair
 4 using namespace std;
 5 
 6 const int N = 2e3 + 50;
 7 const int inf = 0x3f3f3f3f;
 8 int B = 95, n;
 9 int dp[2][N][180][180], a[N];
10 
11 int dfs(int l, int r, int k, int op) {
12     int d = (l - 1) - (n - r);
13     int &ans = dp[op][l][B + d][k];
14     if(ans != -1) return ans;
15     int ret;
16     if(op == 0) {
17         if(l + k - 1 == r) return dp[op][l][B + d][k] = a[r] - a[l - 1];
18         else if(l + k - 1 > r)  return dp[op][l][B + d][k] = 0;
19         
20         int ret1 = dfs(l + k, r, k, op ^ 1) + a[l + k -1] - a[l - 1];
21         int ret2 = dfs(l + k + 1, r, k + 1, op ^ 1) + a[l + k] - a[l - 1];
22         ret = max(ret1, ret2);
23     } else {
24         if(l + k - 1 == r) return dp[op][l][B + d][k] = -a[r] + a[l - 1];
25         else if(l + k - 1 > r)  return dp[op][l][B + d][k] = 0;
26         
27         int ret1 = dfs(l, r - k, k, op ^ 1) - a[r] + a[r - k];
28         int ret2 = dfs(l, r - k - 1, k + 1, op ^ 1) - a[r] + a[r - k - 1];
29         ret = min(ret1, ret2);
30     }
31     return dp[op][l][d + B][k] = ret;
32 }
33 int main() {
34     memset(dp, -1, sizeof(dp));
35     scanf("%d", &n);
36     for(int i = 1; i <= n; i++)
37         scanf("%d", &a[i]), a[i] += a[i - 1];
38     int ans = dfs(1, n, 1, 0);
39     printf("%d\n", ans);
40     return 0;
41 }
42 /*
43 */

 

posted @ 2018-04-16 19:34  NotNight  阅读(159)  评论(0编辑  收藏  举报