题意:
给一个序列,AB两人比赛,每人每次只能从左或从右取任意连续数,都足够聪明,极力想让自己赢,A先开始取,让你求A和B都取最优策略时,A-B的得分结果。
思路:
初写dp没多久,式子怎么也推不出来,看了题解,原来是这样的:
让sum[i]表示前i个数总和,要求A-B即求 A - (sum[n]- A),即求2*A-sum[n]。
求A的话,让dp[i][j]表示A在第i~j个数中取到的值,则dp[1][n]即为最终要求得的A,有dp[i][j]=(sum[j]-sum[i-1]) - 区间i~j的最小值(m).
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 105;
int arr[N],sum[N],dp[N][N],visit[N][N],n;
int dfs(int i,int j) {
if (visit[i][j])
return dp[i][j];
visit[i][j] = 1;
int k, m = 0;
for (k = i + 1; k <= j; k++)
m = min(m, dfs(k, j));
for (k = i; k < j; k++)
m = min(m, dfs(i, k));
dp[i][j] = sum[j] - sum[i - 1] - m;
return dp[i][j];
}
int main() {
int n;
while (~scanf("%d", &n) && n) {
int i;
memset(visit, 0, sizeof(visit));
for (i = 1; i <= n; i++) {
scanf("%d", &arr[i]);
sum[i] = sum[i - 1] + arr[i];
}
printf("%d\n", 2 * dfs(1, n) - sum[n]);
}
return 0;
}