登山(DP问题-最长上升子序列)
原题链接:
思路分析:
通过读题可知,题目可以理解为:
给定一数组,需要找出最长的子序列,该子序列满足(先单调递增再单调递减!!!)
也就是说,该子序列必有一个拐点!!!
那么,我们可以利用dp的思想,求得把每个点看做拐点所能得到的最长子序列,然后求出最大值即可。
也就是说,我们可以分别求出,每个点作为终点时的最长上升子序列和最长下降子序列,然后加起来减一(该点)
代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<bits/stdc++.h>
#define N 1010
using namespace std;
int f[N], g[N];
int n;
int a[N], b[N];
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
b[n + 1 - i] = a[i];//把a数组倒过来存,方便求最长下降子序列
}
//最长上升子序列【模板】
for (int i = 1; i <= n; i++)
{
f[i] = 1;
for (int j = 1; j < i; j++)
{
if (a[i] > a[j])
{
f[i] = max(f[i], f[j] + 1);
}
}
}
//最长下降子序列
for (int i = 1; i <= n; i++)
{
g[i] = 1;
for (int j = 1; j < i; j++ )
{
if (b[i] > b[j])
{
g[i] = max(g[i], g[j] + 1);
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
ans = max(ans, f[i] + g[n+1-i] - 1);//把i作为拐点,题目要求子序列的最大值
}
cout << ans;
return 0;
}