Description
给出N个正整数,AB两个人轮流取数,A先取。每次可以取任意多个数,直到N个数都被取走。
每次获得的得分为取的数中的最小值,A和B的策略都是尽可能使得自己的得分减去对手的得分更大。
在这样的情况下,最终A的得分减去B的得分为多少。
Input
第一行一个正整数N (N <= 1,000,000),第二行N个正整数(不超过10^9)。
Output
一个正整数,表示最终A与B的分差。
Sample Input
3
1 3 1
1 3 1
Sample Output
2
HINT
第一次A取走3,第二次B取走两个1,最终分差为2。
Source
神$dp$,抄题解还要想半天的那种。。首先我们要排序,这个好理解,因为显然你在那傻不拉几的取小的让别人把大的都拿走了显然是不优的。然后问题可以转化成这样:两个人轮流取数,如果一个数被取走了那么比它更大的数就不能再取了。
然后我们倒着考虑一下,如果A选到$i$停止,那么B从$i+1$处开始选。但是我们要考虑一个问题,因为是倒着考虑的真实的情况下B会比A先选,也就是说B也可以选择取走A的那一份,设当前A能取得最大值是$maxn$,那么B当然可以取到$max(maxn,val[i+1]-maxn)$
最后找到的就是第一个人能取到的最大值
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define M 1000010 6 using namespace std; 7 int n,maxn; 8 int val[M],f[M]; 9 int read() 10 { 11 char ch=getchar(); int x=0; 12 while(ch>'9'||ch<'0') ch=getchar(); 13 while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=getchar(); 14 return x; 15 } 16 int main() 17 { 18 n=read(); 19 for(int i=1;i<=n;i++) val[i]=read(); 20 sort(val+1,val+1+n); 21 maxn=val[1]; 22 for(int i=1;i<=n;i++) 23 { 24 f[i]=maxn; 25 maxn=max(f[i],val[i+1]-f[i]); 26 } 27 printf("%d",f[n]); 28 return 0; 29 }