今天将详解一下最长上升子序列和最大上升子序列这种题,实际上两种题考的是一种题,最大上升子序列只是
稍微改动的最长上升子序列。
还是一样我先给出做题样例和模板。
一.样例
《 超级跳跃》 是一款非常简单的小游戏,它的规则是这样的:
a. 游戏赛道被分为了 N 块区域,每块区域具有一个价值 Ki;
b. 玩家起始站在道路的起点处,当参与者到达终点处时游戏结束;
c. 玩家每次可以选择使用超级跳跃到达前方的任意区域,但到达的区域
必须满足以下两个条件之一: ① 到达的区域是终点; ② 到达的区域
的价值大于当前所在的区域价值。
d. 玩家每到达一个区域,就获得这块区域的价值。
e. 不可以使用超级跳跃向身后跳。
请你编写一个程序,算出对于一条《 超级跳跃》 游戏的赛道,玩家最多可以
获得多少价值。
输入
输入的数据有多组, 每组数据首先是一个正整数 N (0 ≤ N ≤ 1000), 代表
赛道被分为 N 块区域,接下来是 N 个以空格为分隔符的数字 K1, K2 … KN
(−231 ≤ ?? ≤ 231 − 1),代表 N 块区域的价值。每组数据占一行。
若 N 为 0,则表示输入结束,该组数据不输出任何内容。
输出
对于每组数据,在一行内输出一个正整数,表示游戏中可获得的最大价值。
样例输入
3 1 3 2
4 1 2 3 4
4 3 3 2 1
0
样例输出
4
10
3
二.模板
#include<stdio.h>
#include<string.h>
int main(void)
{
int c;
int max[1000]; //这里用来存放到第几个数时的 最长长度 或者 最大子序列和
memset(num,0,1000);
scanf("%d",&c);
for(int i=0;i<c;i++)
scanf("%d",&num[i]);
int caca; //存放对当前数而言上一个满足条件的子序列最大和或者说是最长子序列长度
max[0]=1; //只有一个数时长度为1
//max[0]=num[0]; //求最大子序列和需要如此初始化
for(int j=1;j<c;j++) //num[j]为我们的目标数字,要找到它之前的最长子序列长度或最大子序列和
{
caca=0; //因为num[j]在变,所以每次都要讲caca置为0
for(int k=0;k<j;k++) //k从0开始,标志着我们从num[k]开始遍历num[j]之前的数字,逐个求符合
{ //条件的路线
if(num[j]>num[k])
{
//caca是上一个最大子序列和,max[k]是当前最大子序列和,max[k]一定是已知的,
if(caca<max[k]) 因为你之前肯定算过,外层循环用j算的,那么max[j]之前的一定已经算过了
caca=max[k]; //此时caca是第j个数前的最大子序列
/*
这个地方就是进行筛选,是这个模板的核心部分,求最大上升子序列的时候,
举个例子比如我输入的数字是 1 4 3 5那么,在j=3,也就是5这个数时,当k来
到了2,查找到了3这个数时 此时你的caca是前一个符合条件的子序列的和,
“符合条件”的意思是对5而言可以是子序列的一部分(最后一个数字小于5的上一个序列)
比如在这里1 4就是"上"一个符合条件的子序列的和,同时你需要和 1 3这个符合条件的
子序列比较,看哪一个更大,哪一个就作为5的最大子序列的组成部分。
如果是求最长上升子序列同理,看是走前一条符合条件的路线长,还是走现在的路线长
*/
}
}
max[j]=caca+1; //最长子序列长度加上1为新的最长长度
//max[j]=caca+num[j]; //最大子序列和加上自己为新的最大子序列和
}
int ha=max[0];
for(int i=1;i<c;i++)
{
if(max[i]>ha)
ha=max[i];
}
printf("%d\n",ha); //找到最大的打印出来,无论是最长长度还是和都如此
return 0;
}