Question: uva10891-game of sum (recursive)
The N number is given, and then two friends are playing the game. Each time you can choose one side from the two sides of the number in this row to start to get the continuous number, you must take one or more. Both of them will adopt the best strategy to get the number, and ask the first partner to get the sum of the number and the difference between the sum of the number and the number of the 2nd friends.
Solution: At the beginning, there was no clue about this question. As long as there was a question about the game idea, there was no idea. You can understand the problem after reading other people's questions.
In simple terms, if each partner can only get one number from both sides, DP [I] [J ]: the maximum value that a partner can obtain from number I to number J; sum [I] [J]: the continuous sum of number I to number J.
Recursive DP [I] [J] = sum [I] [J]-min (DP [I + 1] [J ], DP [I] [J-1 ]);
This is a continuous number. Recurrence: DP [I] [J] = sum [I] [J]-min (DP [I + k] [J], DP [I] [J-K], 0); k> = 1 & K <= J-I-1. 0 indicates that all numbers are selected. Here, why do we not use the largest sum, but use the sum of the sum to subtract the smallest sum? I think this is because of the need for recursion, in addition, the first partner must have the largest choice for the other partner. Therefore, the first partner must have the smallest value after obtaining the number, in this way, the first partner can get more and the second will get less.
Code:
#include <cstdio>#include <cstring>typedef long long ll;const int N = 105;const ll INF = 0x3f3f3f3f;ll dp[N][N], sum[N];int v[N];int n;void init () {memset (sum , 0, sizeof (sum));for (int i = n; i >= 1; i--) {if (i == n)sum[i] = v[i];elsesum[i] = sum[i + 1] + v[i];//printf ("%lld\n", sum[i]);dp[i][i] = v[i]; }}ll Min (const ll a, const ll b) { return a < b? a: b; }int main () {while (scanf ("%d", &n) && n) {for (int i = 1; i <= n; i++)scanf ("%d", &v[i]);init ();ll mm;for (int len = 1; len < n; len++)for (int i = 1; i + len <= n; i++) {mm = INF;//printf ("%lld\n", mm);for (int k = 1; k <= len; k++)mm = Min (mm, Min (dp[i + k][i + len], dp[i][i + len - k]));dp[i][i + len] = sum[i] - sum[i + len + 1] - Min (0, mm); }//printf ("%lld\n", dp[1][n]);printf ("%lld\n", 2 * dp[1][n] - sum[1]);}return 0;}