1996:登山(2.6基本算法之动态规划)

来源:互联网 发布:spark 大数据分析 编辑:程序博客网 时间:2024/06/05 04:56

1996:登山

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

输入
Line 1: N (2 <= N <= 1000) 景点数
Line 2: N个整数,每个景点的海拔
输出
最多能浏览的景点数
样例输入
8
186 186 150 200 160 130 197 220
样例输出
4

分析:

和Maximum sum有点相似,不同点是那个题是求的连续子集和,这个是上升子序列问题,所以这个题的dp[i]就是到i位置最长的序列了,不需要另一个数组的存储。下面代码里面是用struct存储的两个dp,所以需要有一个的初始化为0,避免重复。如果用两个dp数组就不需要考虑这个问题,从某一位置分开就可以了。

#include <iostream>#include<algorithm>using namespace std; //http://noi.openjudge.cn/ch0206/1996/struct node{    int le,ri;};int n,a[1100];node dp[1100];void f(){    int ans=1;    for(int i=1;i<=n;i++){        dp[i].le=1;        dp[i].ri=0;        //cout<<dp[i].le<<" "<<dp[i].ri<<endl;    }    for(int i=2;i<=n;i++){        for(int j=1;j<i;j++){            if(a[i]>a[j]){                dp[i].le=max(dp[i].le,dp[j].le+1);            }        }    }    for(int i=n;i>=1;i--){        for(int j=n;j>i;j--){            if(a[i]>a[j]){                dp[i].ri=max(dp[i].ri,dp[j].ri+1);            }        }        ans=max(ans,dp[i].le+dp[i].ri);    }    cout<<ans<<endl;}int main(int argc, char *argv[]) {    while(cin>>n){        for(int i=1;i<=n;i++){            cin>>a[i];        }        f();    }    return 0;}
原创粉丝点击