传送门:
http://acm.hdu.edu.cn/showproblem.php?pid=5623
shit这道题目居然是原题
BZOJ 2091 Poi2010 The Minima Game 动态规划
当时比赛怎么就没注意一下呢,不然又可以多对一道题目了!!
不过这种策略性的dp倒也是第一次见,也想了一段时间才懂这种策略
题目大意:给定n 个数,两个人轮流取,每次可以取走任意一些数,获得的分值是这些数中的最小值
两个人都想让自己的分值-对方的分值最大,求最终先手得分-后手得分
显然每个人取走的都是当前剩下的数中最大的一些数
那么考虑倒着做,令f i 表示剩余最小的i 个数时先手-后手的最大差值
那么有DP方程f i =max{a j+1 −f j }(0≤j<i)
维护个最大值就行了
为什么是减呢,因为每个人都是使用的最优策略,我们姑且可以这样看,上一次取完,对这一次取得是不利的,可以看做是先手后手是轮流与换的,因此是要减的!!维护一个最大值就ok了!!!
#include <cstdio>
#include <algorithm>
using namespace std;
long long dp[50010];
int a[50010];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int N;
scanf("%d", &N);
for (int i = 0; i < N; ++i)
scanf("%d", &a[i]);
sort(a, a + N);
dp[0] = 0;
long long mx = -1e18;
for (int i = 0; i < N; ++i)
{
mx = max(mx, a[i] - dp[i]);
dp[i + 1] = mx;
}
printf("%I64d\n", dp[N]);
}
return 0;
}