UVa UVA 10891 Game of Sum (區間DP)
阿新 • • 發佈:2019-02-17
/** * 挺水的區間DP * dp[i][j] 表示該輪選手在還剩[i,j]的數中按規則選取所能得到的最大收益 * 最大收益也就是相對於當前選手最優決策後在區間[i,j]中使得兩選手的差值最大。 * 這樣dp[1][n]其實就是所要的答案。 * 如何求dp[1][n],其實就是個區間dp,從小範圍算起到最後1-n範圍。 * 再用個sum[n]陣列記錄前n項和,方便求區間[i,j]的和。 * 具體狀態轉移方程看程式碼,和普通的區間dp一樣,列舉z = i->j 如何根據遊戲規則取最大值 */ #include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <string> #include <queue> #include <map> #include <vector> #include <algorithm> #define DEBUG 0 #define INF 0x7fffffff #define MAXN 105 typedef long long LL; using namespace std; int n, sum[MAXN], dp[MAXN][MAXN]; void dp_func() { for(int k = 2; k <= n; k ++) { for(int i = 1; i <= n - k + 1; i ++) { int j = i + k - 1, curMax = -INF, ans; for(int z = i; z <= j; z ++) { int cur = sum[z] - sum[i-1] - dp[z+1][j]; if(cur > curMax) { curMax = cur; } } for(int z = j; z >= i; z --) { int cur = sum[j] - sum[z-1] - dp[i][z-1]; if(cur > curMax) curMax = cur; } dp[i][j] = curMax; } } cout << dp[1][n] << endl; } int main() { while(cin >> n && n) { sum[0] = 0; memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i ++) { cin >> dp[i][i]; sum[i] = sum[i-1] + dp[i][i]; } dp_func(); } return 0; }