【题解】登山
【题目描述】
五一到了,ACM队组织大家去登山观光,队员们发现山上一共有N个景点,并且决定按照顺序来浏览这些景点,即每次所浏览景点的编号都要大于前一个浏览景点的编号。同时队员们还有另一个登山习惯,就是不连续浏览海拔相同的两个景点,并且一旦开始下山,就不再向上走了。队员们希望在满足上面条件的同时,尽可能多的浏览景点,你能帮他们找出最多可能浏览的景点数么?
【输入描述】
第一行:N (2 <= N <= 1000) 景点数;
第二行:N个整数,每个景点的海拔。
【输出描述】
最多能浏览的景点数。
【样例输入】
8 186 186 150 200 160 130 197 220
【样例输出】
4
【题目分析】
根据题目上面的图片,我们按照类似与上面这样的顶点进行划分。
假设:
a[1]是顶点,
a[2]是顶点,
a[3]是顶点,
....
a[n-1]是顶点,
a[n]是顶点。
我们假设顶点是a[k],上山和下山这两段是完全独立的。
为了让最终结果最大,只需要分别使两段的结果最大即可。类似:怪盗基德 那道题。
我们定义两个数组,f[i]表示从左往右求,以a[i]为结尾的最长上升序列的最长长度。
g[i]表示从右往左求,以a[i]为结尾的最长上升序列的最长长度(从左往右看是最长下降子序列)。
那么以a[k]为顶点的最大结果= f[k]+g[k]-1( a[k]被算了两次)
【参考答案】
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int maxn=1e3+5; int a[maxn],b[maxn],c[maxn]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++)//找出上升序列的最长序列 { b[i]=1; for(int j=1;j<i;j++) if(a[j]<a[i]) b[i]=max(b[i],b[j]+1); } for(int i=n;i>=1;i--)//找出下降序列的最长序列 { c[i]=1; for(int j=n;j>i;j--) if(a[j]<a[i]) c[i]=max(c[i],c[j]+1); } int sum=0; for(int i=1;i<=n;i++) sum=max(c[i]+b[i],sum); printf("%d\n",sum-1);//因为上升序列和下降序列公用一个顶点 }
扫描二维码推送至手机访问。
版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。