[POJ1678] I Love this Game! - 博弈,DP

I Love this Game!
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 2334   Accepted: 916

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.

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



提交地址POJ



题解:

我太菜了想不到;
我们假设两个人分别选了A,B,C,D,E,F;
那么ans = A - B + C - D + E - F;
整理一下 ans = A - (B - (C - (D - (E - F))));
我们发现这是一堆子问题想到了递归;
如果先手选了A,那么后手肯定要最大化(B - (C - (D - (E - F))),来使自己获得最大收益;
同样后手选择了B之后,先手又要最大化(C - (D - (E - F))来满足自己的最大利益;
这样我们设f[i]表示从第i个物品开始,并且先手选第i个物品的最大值;
这样每一步都满足属于自己的最大收益;
来一波记忆化搜索;
对了, 由题意可知a, b > 0, 所以先排个序, 因为每一个人都要从后面选择数;



Code:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 #define inf 1e9
 7 
 8 int T;
 9 int n, a, b;
10 int num[10010];
11 int f[10010];
12 
13 inline int dp(int x)
14 {
15     if (f[x] != -1) return f[x];
16     int ans = -inf;
17     for (register int i = x + 1 ; i <= n ; i ++)
18     {
19         if (num[i] - num[x] >= a and num[i] - num[x] <= b)
20         {
21             ans = max(ans, dp(i));
22         }
23     }
24     return ans == -inf ? f[x] = num[x] : f[x] = num[x] - ans;
25 }
26 
27 inline int solve()
28 {
29     int ans = -inf;
30     for (register int i = 1 ; i <= n ; i ++)
31         if (num[i] >= a and num[i] <= b)
32             ans = max(ans, dp(i));
33             
34     return ans == -inf ? 0 : ans;
35 }
36 
37 int main()
38 {
39     cin >> T;
40     while (T--)
41     {
42         scanf("%d%d%d", &n, &a, &b);
43         for (register int i = 1 ; i <= n ; i ++) scanf("%d", &num[i]);
44         sort(num+1, num+1+n);
45         memset(f, -1, sizeof f);
46         printf("%d\n", solve());
47     }
48     return 0;
49 }
 
 

猜你喜欢

转载自www.cnblogs.com/zZh-Brim/p/9160717.html