题目描述
Alice: 上课好无聊啊!!!
Bob:那你想干嘛?
Alice:我们来玩游戏好伐?
Bob:好哇!咋玩?
Alice:我们写n个正整数,然后轮流拿数字,每次可以拿任意多个,每次的得分是这次拿的数字中的最小值,我们俩每次拿数都要让自己的得分与对方的得分差值最大化,我俩试着拿一拿看看最后我比你高多少分吧~
Bob:我拒绝,这明明O(瞬间)就知道答案了为啥还要玩儿
Alice:哇你好厉害,那我写n个数你说按刚才的策略,我先拿,最后比你高多少分,你要是答对了我就嘻嘻嘻
Bob:好,你等着,嘿嘿嘿
输入
第一行输入一个整数T表示用例组数,每组用例第一行输入一个整数n表示要拿的正整数个数,之后输入n个正整数ai
输出
每组用例输出一个整数占一行,表示两人按游戏策略拿完所有数字后Alice比Bob高多少分
数据范围
1<=T<=10,1<=n<=50000,1<=ai<=10^9
样例输入
1
3
1 3 1
样例输出
2
样例解释
Alice拿3,Bob拿1 1,最后两者得分差值是3-1=2
题解:
一开始没读懂题意,后来上网搜,竟然搜到了原题。。(KK's number)这个题的意思是每个人拿的时候目的都是自己减去对方的得分最大,题目没有说清楚。
至于怎么拿?要是我单独做的话我也没有什么思路。。可是我搜题意的时候竟然也搜到了题解。。用dp做,就是找只有前i个数时候的当前最优解,然后让i不断变大直到n为止即可。递推公式就是dp[i] = max(dp[i-1], a[i] - dp[i - 1]),三十行就能写完。
感觉dp真是一个黑科技啊。。。但是思考什么时候用dp,以及得到递推公式,是一个挺麻烦的过程。。。
AC代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int comp(const void*a,const void*b)
{
return *(long long int*)a - *(long long int*)b;
}
long long int a[50005],dp[50005];
long long max(long long a, long long b)
{
return a > b ? a : b;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int n;
scanf("%d", &n);
int i;
for (i = 0; i < n; i++)
scanf("%lld", &a[i]);
qsort(a, n, sizeof(long long int), comp);
long long ans = 0;
dp[0] = 0;
for (i = 1; i < n; i++)
dp[i] = max(dp[i-1], a[i] - dp[i - 1]);
printf("%lld\n", dp[n - 1]);
}
return 0;
}