首页 > 代码库 > 1176. Two Ends

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.\n", ++count, dp(0,n-1));53     }54     return 0;55 }

 

1176. Two Ends