1176. Two Ends

题目链接地址:http://soj.me/1176

题目大意:两头取数。第一个人随机取,第二个人用贪婪算法(每次都取大的),求两人取数在第一个人赢的情况下的最大分差。使用贪婪算法时,如果左右两边相等,取左边的。

核心算法:动态规划。

          设数组arr[a][b]是在数列区间[a,b]上的最大分差。

          递推公式:

          1.第一个人取左边的数arr[a]

            if(arr[a+1] >=  arr[b])  point1 = input[a] - input[a+1] + dp(a+2,b);

            else point1 = input[a] - input[b] + dp(a+1, b-1);

          2.第一个人取右边的数arr[b]

            if (input[a] >= input[b-1]) point2 = input[b] - input[a] + dp(a+1,b-1);

            else point2 = input[b] - input[b-1] + dp(a,b-2);

          arr[a][b] = point1 > point2 ? point1 : point2;

代码:

 1 // 动态规划!
 2 #include <stdio.h>
 3 
 4 #define N 1005
 5 #define ENDLESS 100000
 6 
 7 int arr[N][N];
 8 int input[N];
 9 
10 int dp(int a, int b) {
11     if (arr[a][b] != ENDLESS)
12         return arr[a][b];
13 
14     if (a > b)
15         return 0;
16 
17     // 第一个人取左边的数,第二个人贪婪算法
18     int point1;
19     if (input[a+1] >= input[b]) {
20         point1 = input[a] - input[a+1] + dp(a+2,b);
21     } else {
22         point1 = input[a] - input[b] + dp(a+1, b-1);
23     }
24 
25     // 第一个人取右边的数,第二个人贪婪算法
26     int point2;
27     if (input[a] >= input[b-1]) {
28         point2 = input[b] - input[a] + dp(a+1,b-1);
29     } else {
30         point2 = input[b] - input[b-1] + dp(a,b-2);
31     }
32 
33     arr[a][b] = point1 > point2 ? point1 : point2;
34 
35     return arr[a][b];
36 }
37 
38 int main() {
39     int n;
40     int count = 0;
41     while (scanf("%d", &n) != EOF) {
42         if (n == 0)
43             break;
44 
45         for (int i = 0; i < n; i++)
46             scanf("%d", &input[i]);
47 
48         for (int i = 0; i < n; i++)
49             for (int j = 0; j < n; j++)
50                 arr[i][j] = ENDLESS;
51 
52         printf("In game %d, the greedy strategy might lose by as many as %d points.
", ++count, dp(0,n-1));
53     }
54     return 0;
55 }
原文地址:https://www.cnblogs.com/AminHuang/p/4013028.html