题目:有两个人A、B轮流在一串数字中取走一部分,每次只能从一侧取数,可以全取走但至少去一个,
A先取,问A最大能比B大多少,两个人都很聪明。
分析:动态规划(DP),区间DP。因为数字的总和是定值,所以差值最大就是A取走的数字的和最大。
状态定义:f(s,e)为在区间 [s, e] 上能取得的最大值;
转移方程:f(s,e)= max(sum(s,e),lmax(s,e),rmax(s,e));
lmax = max( sum(s,k)+ (sum(k+1,e)- f(k+1,e)));
rmax= max( (sum(s,k-1)- f(s,k-1))+ sum(k,e));
说明:A在区间 [s, e] 上取走一部分是,B一定会取走剩下部分的最优解。
#include <stdio.h>
#include <stdlib.h>
int f[101][101];
int sum[101][101];
int data[101];
int main()
{
int n;
while (~scanf("%d",&n) && n) {
for (int i = 1; i <= n; ++ i) {
scanf("%d",&data[i]);
}
for (int i = 1; i <= n; ++ i) {
sum[i][i] = data[i];
for (int j = i+1; j <= n; ++ j) {
sum[i][j] = sum[i][j-1] + data[j];
}
}
for (int i = 1; i <= n; ++ i) {
for (int j = 1; j <= n; ++ j) {
f[i][j] = 0;
}
}
//dp
for (int l = 1; l <= n; ++ l) {
for (int s = 1; s+l-1 <= n; ++ s) {
int e = s+l-1;
f[s][e] = sum[s][e];
for (int k = s; k < e; ++ k) { // left
if (f[s][e] < sum[s][e] - f[k+1][e]) {
f[s][e] = sum[s][e] - f[k+1][e];
}
}
for (int k = e; k > s; -- k) { // right
if (f[s][e] < sum[s][e] - f[s][k-1]) {
f[s][e] = sum[s][e] - f[s][k-1];
}
}
}
}
printf("%d\n",2*f[1][n]-sum[1][n]);
}
return 0;
}