题意:A与B玩游戏,从一列数,n个(0 < n <= 100)中,每次可以从左端或者右端连续的取几个数,直到所有数被取完,问最后A取的数的和减去B取的数的和是多少。
——>>设d[i][j]为下标从i到j的序列中先手最高得分。
状态转移方程:
d[i][j] = sum[i][j] - min(d[i+1][j], d[i+2][j], ..., d[j][j], d[i][j-1], d[i][j-2], ..., d[i][i], 0);
设l[i][j] = min(d[i][j], d[i+1][j], d[i+2][j], ..., d[j][j]);
则l[i][j] = min(d[i][j], l[i+1][j]);
r[i][j] = min(d[i][j], d[i][j-1], d[i][j-2], ..., d[i][i]);
则r[i][j] = min(d[i][j], r[i][j-1]);
则d[i][j] = sum[i][j] - min(l[i+1][j], r[i][j-1], 0);
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100 + 10;
int main()
{
int n, a[maxn], sum[maxn], l[maxn][maxn], r[maxn][maxn], d[maxn][maxn], i, j;
while(scanf("%d", &n) == 1 && n)
{
sum[0] = 0;
for(i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
for(i = 1; i <= n; i++) d[i][i] = l[i][i] = r[i][i] = a[i]; //边界
for(int L = 1; L < n; L++) //递推
for(i = 1; i+L <= n; i++)
{
j = i + L;
int m = 0;
m = min(m, l[i+1][j]);
m = min(m, r[i][j-1]);
d[i][j] = sum[j] - sum[i-1] - m;
l[i][j] = min(d[i][j], l[i+1][j]);
r[i][j] = min(d[i][j], r[i][j-1]);
}
printf("%d\n", 2*d[1][n] - sum[n]);
}
return 0;
}