一本通1283 登山

【题目描述】

五一到了,ACM队组织大家去登山观光,队员们发现山上一共有N个景点,并且决定按照顺序来浏览这些景点,即每次所浏览景点的编号都要大于前一个浏览景点的编号。同时队员们还有另一个登山习惯,就是不连续浏览海拔相同的两个景点,并且一旦开始下山,就不再向上走了。队员们希望在满足上面条件的同时,尽可能多的浏览景点,你能帮他们找出最多可能浏览的景点数么?

【输入】

第一行:N (2 ≤ N ≤ 1000) 景点数;

第二行:N个整数,每个景点的海拔。

【输出】

最多能浏览的景点数。

【输入样例】

8
186 186 150 200 160 130 197 220

【输出样例】

4


首先分析一下这个题的思路(这很关键!!!),最简单直白的一个条件就是不爬海拔相同的山,也就是没有相等的情况。
他们一旦下山就不会再往上爬了,也就是说要想浏览尽可能多的景色,他们应该选择上山加上下山的最长路径,
那么问题就转化为了找到那一个以它作为末尾的上升序列和以它作为开头的下降序列和最大的那一个点


代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int main()
{
int n,maxn=0;
cin>>n;
int a[n],f[n],t[n];//开两个数组,来分别记录上升序列和下降序列
for(int i=0;i<n;i++)
{
cin>>a[i];
f[i]=1;
t[i]=1;//都初始化为1
}
for(int i=0;i<n;i++)
{
for(int j=0;j<i;j++)
{
if(a[j]<a[i])
f[i]=max(f[j]+1,f[i]);
}
}//经典dp,不必多说
for(int i=n-1;i>=0;i--)//这里是重点,因为下降序列不是以这个点为结尾,而是以它为开头的,所以要倒过来(我一开始就是正着写的,然后没过,当然也不一定不行,我是蒟蒻)
{
for(int j=n-1;j>i;j--)//同理,下面的也要倒过来
{
if(a[j]<a[i])
t[i]=max(t[j]+1,t[i]);
}
}
for(int i=0;i<n;i++)
{
maxn=max(maxn,f[i]+t[i]-1);//然后,他就转化成为了一道一般的dp题
}
cout<<maxn;
return 0;
}

总结:思路很重要!!!!

原文地址:https://www.cnblogs.com/57xmz/p/12489993.html