hdu-1087 Super Jupmping ! Jumping ! Jumping

基础之基础之中的基础,然而很简单

简单的动态规划,最长上升子序列 LIS(Longest Increasing Subsequence)

dp[i]表示第i个数结尾的最长上升子序列的长度

初始是dp[i]=1;seg[i]储存第i个数;

求第 i 个的最长LIS 就是求 max j (< i)的LIS加上 1,

状态转移方程dp[i]=max(dp[i],dp[j]+1);

如果seg[j]<seg[i]并且j<i的话,就更新,取最大值;

这个题用的是值,每次更新的时候取值最大的,

 1 # include <cstdio>
 2 # include <iostream>
 3 # include <algorithm>
 4 # include <cstring>
 5 using namespace std;
 6 
 7 int n;
 8 const int maxn=1e3+5;
 9 int dp[maxn],seg[maxn];
10 
11 int main(){
12     while(scanf("%d",&n)!=EOF&&n){
13         for(int i=0;i<n;i++)
14             scanf("%d",&seg[i]);
15         int ans=0;
16         for(int i=0;i<n;i++){
17             dp[i]=seg[i];
18             for(int j=0;j<i;j++){
19                 if(dp[i]<dp[j]+seg[i]&&seg[j]<seg[i]){
20                     dp[i]=max(dp[i],dp[j]+seg[i]);
21                 }
22             }
23             ans=max(ans,dp[i]);
24         }
25         printf("%d\n",ans);
26     }
27     return 0;
28 }
View Code

上面的这个时间复杂度(n*n),

还有一种时间复杂度为(nlogn)的做法,用一个栈来维护一个从大到小的数列

对于当前的数 x 如果大于栈顶的元素的话,就加入栈,

否则的话就在当前的栈内二分查找第一个大于或等于 x 的数,并替换它,

 1 int a[maxn];
 2 int stack[maxn];//储存最大上升子序列的栈
 3 int top;//栈顶
 4 int l;//数组的长度
 5 
 6 void solve(){
 7     top=0,stack[top]=-INF;
 8     for(int i=1;i<=l;i++){
 9         int t=stack[top];
10         if(a[i]>t) stack[++top]=t;
11         else {
12             int ls=0,rs=top;//二分搜索第一个大于等于a[i ]的元素
13             while(rs-ls>1){
14                 int mid=(rs+ls)>>1;
15                 if(stack[mid]>=t) rs=mid;
16                 else ls=mid;
17             }
18             stack[rs]=t;
19         }
20     }
21     cout<<top<<endl;//最后所求的top就是最长上升子序列  
22 }
View Code

 

 

  

posted @ 2017-04-28 22:36  林探惜  阅读(146)  评论(0编辑  收藏  举报