1. 程式人生 > >HDU 1087 Super Jumping! Jumping! Jumping

HDU 1087 Super Jumping! Jumping! Jumping

Super Jumping! Jumping! Jumping!

  Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. Maybe you are a good boy, and know little about this game, so I introduce it to you now. 



  The game can be played by two or more than two players. It consists of a chessboard(棋盤)and some chessmen(棋子), and all chessmen are marked by a positive integer or “start” or “end”. The player starts from start-point and must jumps into end-point finally. In the course of jumping, the player will visit the chessmen in the path, but everyone must jumps from one chessman to another absolutely bigger (you can assume start-point is a minimum and end-point is a maximum.). And all players cannot go backwards. One jumping can go from a chessman to next, also can go across many chessmen, and even you can straightly get to end-point from start-point. Of course you get zero point in this situation. A player is a winner if and only if he can get a bigger score according to his jumping solution. Note that your score comes from the sum of value on the chessmen in you jumping path. 
Your task is to output the maximum value according to the given chessmen list. 

Input

  Input contains multiple test cases. Each test case is described in a line as follow: 
  N value_1 value_2 …value_N 
  It is guarantied that N is not more than 1000 and all value_i are in the range of 32-int. 
  A test case starting with 0 terminates the input and this test case is not to be processed. 
Output

  For each case, print the maximum according to rules, and one line one case. 
Sample Input

3 1 3 2
4 1 2 3 4
4 3 3 2 1
0

解題思路:
  本題有多組資料,每組資料給出棋子數量,棋子權值,玩家從起始位置上跳到棋子上,每次只能向後跳,且只能跳到比當前棋子權值大的棋子上。要求輸出玩家跳過棋子的權值之和的最大值。

  這其實就是一個給定陣列求最大升序子串權值和(最大升序子串在原陣列中不一定連續)的問題。可以用陣列dp儲存以每個點為結尾的陣列的最大升序子串權值和(dp[i]為以原陣列中以第i個數為結尾的最大升序子串權值和)這樣對每個i都會出現兩種情況。

  1、第 i 號元素之前所有元素的權值都比第 i 號元素大,那麼以第 i 號元素為結尾的最大升序子串權值和就為第 i 號元素自己的權值。

  2、第 i 號元素之前存在比其權值小的元素(設其為 j )則第 i 號元素的最大升序子串權值和為第 j 號元素的最大升序子串權值和再加上第 i 號元素的權值。

知道這兩種情況後便可以寫出動態規劃狀態轉移方程 dp[i] = max{1, dp[j] + 1}   (j : 1 ~ i - 1)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e4+100;
 4 int arrays[maxn];   //棋子陣列
 5 int dp[maxn];   //以每個棋子為結尾的最大升序子串權值和
 6 int main()
 7 {
 8     int n;  //輸入棋子數量
 9     while(scanf("%d", &n) != EOF){
10         if(n == 0)  //棋子數為0結束
11             break;
12         for(int i = 1; i <= n ; i++){
13             scanf("%d", &arrays[i]);    //輸入棋子權值
14         }
15         int ans = -1;   //ans記錄整個陣列最大升序子串權值和
16         for(int i = 1; i <= n; i++){
17             dp[i] = arrays[i];  
18             //初始化第 i 號元素為結尾的最大升序子串權值和就為第 i 號元素自己的權值
19             for(int j = 1;  j < i; j++){    //遍歷起始位置到i
20                 if(arrays[i] > arrays[j] && dp[j] + arrays[i] > dp[i]){
21                 //如果找到j權值小於i且以j元素結尾的最大升序子串權值和 加上i的權值 大於當前記錄的權值和
22                     dp[i] = dp[j] + arrays[i];//更新當前記錄
23                 }
24             }
25             ans = max(ans, dp[i]);  //始終保持ans為dp中最大值
26         }
27         printf("%d\n", ans);
28     }
29     return 0;
30 }