运用方法:动态划归

问题描述:

如今,一种被称为“超级跳!跳!跳!”的棋类游戏在杭电很流行。也许你是一个好孩子,多少了解这个游戏,所以我给你介绍一下。

这个游戏可两个或者两人以上进行。它包含一个棋盘和一些棋子,所有棋子标记一个正整数或“开始”或“结束”。玩家开始于开始点,必须最终跳到终止点。在跳的期间(in the course of jumping),玩家将会在路劲中访问棋子,但是所有人必须从一个棋子到另一个绝对大处(你可以假设开始点是一个最小的,终止点是一个最大的。)。所有玩家不能悔棋。每一跳可以从一个棋子去另一个,也可以越过很多棋子,甚至你可以直接从起始点到终止点。当然这种情况下你只能得零分。胜利者必须能用他的解决方案获得最高的分数。你的成绩来源于你所跳过路径的棋子值之和。

你的任务是根据所给的棋子列表输出最大值。

输入:

输入包含多个测试样例。每个测试样例描述为如下一行:

N value_1 value_2 …value_N 

必须保证N不大于1000,所有的value_i在32-int范围内(in the range of)。

一个测试样例以0开始且终止输入,则这个测试样例不会被处理。

输出:

对于每一个样例,根据规则打印最大值,一行一个样例。

Sample Input
3 1 3 2
4 1 2 3 4
4 3 3 2 1
0
 
Sample Output
4
10
3
 
题目思路:
注意,求解最大递增子序列和,这里要特别注意一点:这个题目不要求是连续的最大递增子序列。但是一定要注意是递增的。
dp数组表示是包含当前这个数的最大递增子序列和。dp[i]表示的是前i个并且包含第i个的最大递增子序列和!给个数据:3 1 4 显然dp[1]=3,dp[2]=1表示两个数的最大值。因为分两种情况讨论,如果第二个数大于第一个数,就加上,即dp[2]=dp[1]+num[2];如果不大,dp[2]=num[2]; dp[3]=7表示三个数的最大值。首先比较num[3]和num[1],如果num[3]>num[1],dp[3]=7先存下来,如果num[3]>num[2],dp[3]=5依旧存下来;还有一种如果num[3]比前两个值都小,dp[3]=num[3];最后在存下来的dp[3]中找到一个最大的!
AC代码:
 
Online Judge    Online Exercise    Online Teaching    Online Contests    Exercise Author
F.A.Q
Hand In Hand
Online Acmers    
Forum | Discuss
Statistical Charts
Problem Archive
Realtime Judge Status
Authors Ranklist

 Search    
     C/C++/Java Exams     
ACM Steps
Go to Job
Contest LiveCast
ICPC@China
Best Coder beta
VIP | STD Contests
Virtual Contests 
    DIY | Web-DIY beta
Recent Contests
Author hsinhsia
Mail Mail 0(0)
Control Panel Control Panel 
Sign Out Sign Out
View Code

Problem : 1087 ( Super Jumping! Jumping! Jumping! )     Judge Status : Accepted
RunId : 23388301    Language : G++    Author : hsinhsia
Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int num[1010],dp[1010];

int main ()
{
    int n,Max;
    while (~scanf("%d",&n))
    {
        if (n==0)
            break;
        Max=0;
        memset(dp,0,sizeof(dp));
        for (int i=0;i<n;i++)
        {
            scanf("%d",&num[i]);
        }
        dp[0]=num[0];
        for (int i=1;i<n;i++)
        {
            for (int j=0;j<i;j++)
            {
                if (num[i]>num[j])
                dp[i]=max(dp[i],dp[j]+num[i]);
            }
            dp[i]=max(dp[i],num[i]);
        }
        for (int i=0;i<n;i++)
        {
            Max=max(Max,dp[i]);
        }
        printf ("%d\n",Max);
    }
    return 0;
}

 

问题代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int MAXN = 1000;
//record the maximum of sub-string
int dp[MAXN];
//record the input number
int num[MAXN];
using namespace std;
bool cmp(int a, int b){
    //order by decreasing
    return a > b;
}
int main(){

    // ~是按位取反
    //scanf的返回值是输入值的个数
    //如果没有输入值就是返回-1
    //-1按位取反结果是0
    //while(~scanf("%d", &n))就是当没有输入的时候退出循环
    int n;
    while(~scanf("%d",&n)){
        if(n == 0)
            break;
        //initialize the dp
        memset(dp, -1, sizeof(int));
        for(int i = 0; i < n; i++){
            scanf("%d",&num[i]);
        }
        dp[0] = num[0];
        for(int i = 1; i <= n; i++){
            if(num[i-1] < num[i]){
                dp[i] = dp[i-1] + num[i];
            }
            else
                dp[i] = num[i];
        }
        sort(dp,dp+n,cmp);
        printf("%d\n", dp[0]);
    }
    return 0;
}