題目描述
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;
}