I Love this Game!
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 1270 | Accepted: 458 |
Description
A traditional game is played between two players on a pool of n numbers (not necessarily distinguishing ones).
The first player will choose from the pool a number x1 lying in [a, b] (0 < a < b), which means a <= x1 <= b. Next the second player should choose a number y1 such that y1 - x1 lies in [a, b] (Attention! This implies y1 > x1 since a > 0). Then the first player should choose a number x2 such that x2 - y1 lies in [a, b]... The game ends when one of them cannot make a choice. Note that a player MUST NOT skip his turn.
A player's score is determined by the numbers he has chose, by the way:
player1score = x1 + x2 + ...
player2score = y1 + y2 + ...
If you are player1, what is the maximum score difference (player1score - player2score) you can get? It is assumed that player2 plays perfectly.
The first player will choose from the pool a number x1 lying in [a, b] (0 < a < b), which means a <= x1 <= b. Next the second player should choose a number y1 such that y1 - x1 lies in [a, b] (Attention! This implies y1 > x1 since a > 0). Then the first player should choose a number x2 such that x2 - y1 lies in [a, b]... The game ends when one of them cannot make a choice. Note that a player MUST NOT skip his turn.
A player's score is determined by the numbers he has chose, by the way:
player1score = x1 + x2 + ...
player2score = y1 + y2 + ...
If you are player1, what is the maximum score difference (player1score - player2score) you can get? It is assumed that player2 plays perfectly.
Input
The first line contains a single integer t (1 <= t <= 20) indicating the number of test cases. Then follow the t cases. Each case contains exactly two lines. The first line contains three integers, n, a, b (2 <= n <= 10000, 0 < a < b <= 100); the second line contains n integers, the numbers in the pool, any of which lies in [-9999, 9999].
Output
For each case, print the maximum score difference player1 can get. Note that it can be a negative, which means player1 cannot win if player2 plays perfectly.
Sample Input
3 6 1 2 1 3 -2 5 -3 6 2 1 2 -2 -1 2 1 2 1 0
Sample Output
-3 0 1
/* ****************************************************************************************************** 题目大意:有两个小盆友面对一堆数字,第一个小盆友取一个数字x1,x1满足0<a<=x1<=b,然后,两人轮流取数字, 保证与上个人的差值也在[a,b]中。问小盆友1取的数字和减去小盆友2取的数字和的差值最大是好多?求这个最大值。 ****************************************************************************************************** 现在看这题,小盆友1,总想差值尽可能的大,那么,小盆友2取了第i个数后,那么加上剩下的局面最大差值不就可以了?从这里,可以看出,这题其实是无后效性的。 那么在取第i个数时,小盆友肯定会很聪明滴选前面可取的最优局面来取撒。从这里,看出,是从最优推出最优。OK,动态规划。 题目给出0<a,如果我们将所有数字排序,很明显,两个小盆友在从前往后取数。 关于差值,对于小盆友1来说,是把他取的数加到这个差值中,而对于小盆友2来说,是把他取的数从差值中减去。这里,感觉还是比较纠结。 我们观察: a-b c-(a-b)=c-a+b d-(c-a+b)=d-c+a-b e-(d-c+a-b)=e-d+c-a+b …… 观察,对于每个式子而言,正号的可以看成是小盆友1所取的数,负号的可以看成是小盆友2所取的数。如果,我们从后往前做,有: dp[a]=a-b dp[c]=c-a+b dp[d]=d-c+a-b dp[e]=e-d+c-a+b …… 那dp[i]存的就是从i开始,小盆友取位置i的数后最大差值。 所以,这题的解决办法就诞生了。 我们用dp[i]表示小盆友第一个取的数字是i位置的数字。 小盆友1必取第i位置上的数,这是我们的定义,小盆友2很聪明,他就不想让小盆友1取得最大值, 于是,小盆友2选择可取的j中dp[j]最大的一个,这样dp[i]就小盆友1从这里取的差值就小了。 既:dp[i]=a[i]-max{dp[j]}。 */ #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int dp[11000];//dp[i]表示当前我取第i个数而下一个人取第j个数的最大结果 int num[11000]; int n, a, b; bool comp(int x) { return (x >= a && x <= b); } bool cmp(int a, int b) { return a<b; } int main() { int t; scanf("%d", &t); while ( t --){ scanf("%d%d%d", &n, &a, &b); for (int i = 0; i < n; i ++){ scanf("%d", &num[i]); } sort(num, num+n, cmp);//排序之后可以优化查找过程 for (int i = 0; i < n; i ++) dp[i] = num[i];//一开始初始值为num[i],因为如果一开始就有符合要求的数,我肯定会取到 dp[n-1] = num[n-1];//根据DP的定义从后向前倒推 int maxx; for (int i = n-2; i >= 0; i --){//我当前取第num[i]个数 maxx = INT_MIN; for (int j = i+1; j < n; j ++){//根据我取得的num[i]来依次查找到最大的dp[j],因为两人都是按照最优的方法来找的,故会找到当前最大的差值,因为他们都要求自己取到的数导致最终结果尽可能的大 if (comp(num[j]-num[i]) && maxx < dp[j]){ maxx = dp[j]; } if (num[j] - num[i] > b)break; } if (maxx != INT_MIN) dp[i] = num[i] - maxx;//maxx为max{dp[j]} } maxx = INT_MIN; for (int i = 0; i < n; i ++){ if (comp(num[i]) && maxx < dp[i])maxx = dp[i]; if (num[i] > b)break; } if (maxx == INT_MIN)maxx = 0; printf("%d\n", maxx); } return 0; }