hdu 5623 KK's Number(dp)

时间:2024-11-10 22:04:50
问题描述
我们可爱的KK有一个有趣的数学游戏:这个游戏需要两个人,有N\left(1\leq N\leq 5*{10}^{4} \right)N(1≤N≤5∗10​4​​)个数,每次KK都会先拿数。每次可以拿任意多个数,直到NN个数被拿完。每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大。在这样的情况下,最终KK的得分减去对手的得分会是多少?
输入描述
第一行一个数T\left( 1\leq T\leq 10\right)T(1≤T≤10),表示数据组数。
对于每组数据包含两行,第一行一个整数N\left(1\leq N\leq 5*{10}^{4} \right)N(1≤N≤5∗10​4​​),表示个数,第二行NN个正整数(不超过{10}^{9}10​9​​)。
输出描述
对于每一个数据输出一个整数,表示最终KK的得分减去对手的得分。
输入样例
1
3
1 3 1
输出样例
2
Hint
首先KK取走3,然后对手取走两个1,那么最终分差为2。

题解:

首先,对数从小到大排序。

用dp[i]表示,当只有前i个数时,先取的人能够得到的分数差的最大值。 dp[0]=0

那么我们容易得到

dp[1] = a[1]-dp[0].

dp[2] = max(a[2]-dp[1],a[1]-dp[0]) = max(a2-dp[1],dp[1]).

dp[3] = max(a[3]-dp[2],a[2]-dp[1],a[1]-dp[0]) = max(dp[2],a[3]-dp[2])

...

dp[i] = max(a[i]-dp[i-1],dp[i-1]).

计算的时间复杂度o(n),排序o(nlogn),总o(nlogn)

注意到 dp[i] 的计算只有到dp[i-1],因此不需要储存所有dp,对内存进行优化

AC代码:

 #pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<bitset>
#include<map>
#include<vector>
#include<stdlib.h>
using namespace std;
#define ll long long
#define eps 1e-10
#define MOD 1000000007
#define N 60000
#define inf 1e12
int n;
int a[N];
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n); int ans=;
for(int i=;i<n;i++){
ans = max(ans,a[i]-ans);
a[i]=ans;
}
printf("%d\n",ans);
}
return ;
}