http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19461
题目意思大致是给你一串数字,A,B两个人轮流从两端取一段数字并得到该串数字的和的点数,每个人都尽可能的多的点数,问A最多能比B多多少点。
区间dp,一开始打算分AB,但是发现太麻烦了,最后用dp(l,r)表示在区间l~r中先手能赢的的最多点数。假设A是区间(l,r)的先手的话,如果A选择了(l,k )// 或(k+1,r)的数字,那他的得分(l,r)的总分减去B在余下区间作为先手能的到的分。
即dp(l,r) = min(sum - min(dp(l,k), dp(k+1,r)));
最终答案是A的得分减去B的得分 = 2*dp(1,n) - sum;
==>>预处理前缀和。
#include <cstring> #include <iostream> using namespace std; int n; int a[105]; int s[105]; int dp[105][105]; int DP(int l, int r) { if (dp[l][r] != -1) { return dp[l][r]; } if (l == r) { return dp[l][r] = a[l]; } int tmp = 0; for (int k=l; k<r; k++) { tmp = min (tmp, DP(l, k)); tmp = min (tmp, DP(k+1, r)); } return dp[l][r] = s[r] - s[l-1] - tmp; } int main () { while (cin >> n) { if (n == 0) break; for (int i=1; i<=n; i++) { cin >> a[i]; } memset(s, 0, sizeof s); for (int i=1; i<=n; i++) { s[i] = s[i-1] + a[i]; } memset(dp, -1, sizeof dp); cout << 2 * DP(1, n) - s[n] << endl; } return 0; }