传送门:http://acm.bjtu.edu.cn/problem/detail?pid=1688
解题思路:与字符串字典序问题相似,不过本题的要求更为复杂,最初以为可以用贪心解决,不过很显然没这么简单,首先要考虑两边的数字相同的情况,但是同时你又要考虑内部的大小关系,不能让对方拿到过大的金子,一度思维进入僵局,可见当时对于dp还不是很熟悉,而本题明显需要一种动态规划的思想。
解题方法:DP + 前缀和
代码如下:
#include <iostream>
#include <cstdio>
using namespace std;
int sum[505]; //保存前缀和
int a[505]; //save the gold
int dp[505][505];
int main()
{
freopen("test.txt","r",stdin);
int t,i,j;
int l,r;
int total;
int n;
scanf("%d",&t);
for(i=1;i<=t;i++)
{
scanf("%d",&n);
total = 0;
for(j=1;j<=n;j++)
{
scanf("%d",&a[j]);
total += a[j];
sum[j] = total; //记录前缀和
dp[j][j] = a[j];
}
for(l=n;l>0;l--)
{
for(r=l+1;r<=n;r++)
{
int temp1,temp2; //分别模拟从两边取出数字的情况
temp1 = a[l] + sum[r] - sum[l] - dp[l+1][r];
temp2 = a[r] + sum[r-1] - sum[l-1] - dp[l][r-1];//dp【l】【r】认为是从l开始到r由此人来取最后一个数的时候,他能获得的最大数值
dp[l][r] = max(temp1,temp2);
}
}
printf("Case #%d: ",i);
printf("%d %d\n",dp[1][n],total-dp[1][n]);
}
//cout << "Hello world!" << endl;
return 0;
}