1. 程式人生 > >Codeforces Round #380 Div.2 F - Financiers Game

Codeforces Round #380 Div.2 F - Financiers Game

ems 們的 include c++ 超過 fine spa nan 情況下

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 */

Codeforces Round #380 Div.2 F - Financiers Game