子问题:
第n个最长--》第i个最长,当i = n 成立
状态:
maxSum[i] 表示 从第一个元素到第 i 个元素的最长子序列
边界:
i == 1 时, maxSum[i] = 1
转移方程:
n=1时,maxSum[n] = 1;
选择时:标准a[i] 与 a[j] 大小
符合:a[i]>a[j] maxSum[i] =max(maxSum[i], maxSum[j]+1);
不符合:如果没有,则maxSum[i] = 1 (第i个元素前边没有较小的!)
以上,初始化maxSum[i] = 1 (i = 1,2,…,n) 因为无论如何最长子序列不小于1
以int a[] = { 0,1,8,4,9,5,10 };为例
maxSum[i]的变化:...
maxSum[1] = 1
maxSum[2] = max(maxSum[2],maxSum[1]+1) = 2
maxSum[3] = max(maxSum[3],maxSum[1]+1) = 2 其中j = 2 时 没有操作 a[2]>a[3]
maxSum[4] = 3
maxSum[5] = 3
maxSum[6] = 4
在 第 i 个元素之前,只要发现比 a[i] 小的 即 将该 j 位置 的 maxSum[j]+1 再与变化前的maxSum[i]比较选较大值;(毕竟不能 得出maxSum[i]的 maxSum(i -1) +1 就是最大值,所以每次都要比较max)
如下:
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
//递推:效率高
const int N = 10e6;
int a[N];
int maxSum[N];
int main()
{
//LIS
int n;
while (cin >> n)
{
int k;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
maxSum[i] = 1; //i = 1时,即为1,初始化
}
//最长子序列个数,maxSum[i]表示在第i个数时的LIS解
for (int i = 2; i <= n; ++i)
for (int j = 1; j < i; ++j) //把i看作n,对n内求解maxSum
{
if (a[i] > a[j])
maxSum[i] = max(maxSum[i], maxSum[j] + 1);
}
cout << *max_element(maxSum + 1, maxSum + n +1) << '\n';
}
return 0;
}
注:*max_element(begin,end) 取一组数据之中的最大值
将这个题目变一下:
求最大上升子序列之和
思路还是一样,一个是最大和,一个是最长 ,都要求上升
因为由上升顺序在,所以按之前的思路:
子问题:
从第1个到第n个最大和--》到第i个最大和,当i = n 成立
状态:
maxSum[i] 表示 从第一个元素到第 i 个元素的最大子序列和
边界:
i == 1 时, maxSum[i] = a[1] //稍有变化
转移方程:
n=1时,maxSum[n] = a[1];
选择时:选择标准:a[i] 与 a[j] 大小
符合:a[i]>a[j] maxSum[i] =max(maxSum[i], maxSum[j]+1);
不符合:如果没有,则maxSum[i] = a[i] (第i个元素前边没有较小的!取其本身)
以上,初始化maxSum[i] = a[i] (i = 1,2,…,n) 因为无论如何最大上升子序列和不小于其本身
代码大致如下:(没多大变化)
#include <iostream>
#include <algorithm>
using namespace std;
//最大上升子序列和
int a[] = { 0,1,8,4,9,5,10 };
int maxSum[1 << 5];
int main()
{
int n = 6;
maxSum[1] = a[1];
for (int i = 2; i <= 6; ++i)
{
maxSum[i] = a[i];
//决定第i个元素 需要 前i-1个元素的上升序列==》比较范围 是前 i-1 个元素
for (int j = 1; j < i; ++j)
{
if (a[i] > a[j])
maxSum[i] = max(maxSum[j] + a[i], maxSum[i]);
}
cout << *max_element(maxSum + 1, maxSum + 7) << " \n"[i==6];
}
cout << *max_element(maxSum + 1, maxSum + 7);
return 0;
}
Output:
9 9 18 18 28
28
Congratulations!可以goto下边儿这些个地方提升自己了
https://onlinejudge.org/
https://codeforces.com/problemsets/acmsguru
https://atcoder.jp/home
http://acm.hdu.edu.cn/listproblem.php?vol=1
https://leetcode-cn.com/problemset/algorithms/