最长上升子序列输出序列贪心做法

之前做过的最长上升子序列的题只是不需要输出这个序列http://www.cnblogs.com/Scale-the-heights/p/4333346.html

做法就是从左到右扫一遍,可以参见http://blog.csdn.net/shuangde800/article/details/7474903

要输出路径其实也很简单,就开个数组f[]把所有数字在最长上升子序列中第一次出现的位置记录下来,然后逆序遍历,比如我们找到最长上升子序列的长度为n,则我们从后往前找到曾经在最长上升子序列中位置为n的数字储存起来,由于扫描是从后往前的,所以这个数字一定是原序列的一个最长上升子序列中位置为n的数字。以此类推。

详细解释可以参见http://blog.csdn.net/ouckitty/article/details/27801843

我是用lower_bound代替了二分,时间紧迫,没时间详写了,要想详解的可以看下上面的链接,贴个代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
int num[1000010],tmp[1000010],f[1000010];
int main()
{
    int t;
    scanf("%d",&t);
    getchar();
    getchar();
    while(t--){
        int cnt=1;
        string str;
        while(getline(cin,str)){
            int len=str.length();
            if(len==0){
                break;
            }
            int ans=0;
            for(int i=0;i<len;i++){
                ans=10*ans+(str[i]-‘0‘);
            }
            num[cnt++]=ans;
        }
        int s=0;
        for(int i=1;i<cnt;i++){
            if(s==0){
                tmp[s++]=num[1];
                f[1]=0;
            }
            else{
                if(num[i]>tmp[s-1]){
                    f[i]=s;
                    tmp[s++]=num[i];
                }
                else{
                    int low=lower_bound(tmp,tmp+s,num[i])-tmp;
                    if(low<s){
                        tmp[low]=num[i];
                        f[i]=low;
                    }
                }
            }
        }
        cout<<"Max hits: "<<s<<endl;
        int x=s;
        int counter=0;
        for(int i=cnt-1;i>=1;i--){
            if(f[i]==x-1){
                tmp[counter++]=num[i];
                x--;
            }
        }
        for(int i=counter-1;i>=0;i--){
            cout<<tmp[i]<<endl;
        }
        /*for(int i=0;i<s;i++){
            printf("%d\n",tmp[i]);
        }*/
        if(t){
            printf("\n");
        }
    }
    return 0;
}
时间: 2024-08-28 22:07:49

最长上升子序列输出序列贪心做法的相关文章

poj2250 最长上升子序列 + 输出

1 //Accepted 208 KB 0 ms 2 //最长公共上升子序列+输出 3 //dp 4 //输出时用的递归输出,注意条件判断 5 #include <cstdio> 6 #include <cstring> 7 #include <iostream> 8 using namespace std; 9 const int imax_n = 105; 10 const int imax_stringlen = 32; 11 char s1[imax_n][im

【动态规划】【最长上升子序列】【贪心】bzoj1046 [HAOI2007]上升序列

nlogn求出最长上升子序列长度. 对每次询问,贪心地回答.设输入为x.当前数a[i]可能成为答案序列中的第k个,则若 f[i]>=x-k && a[i]>ans[k-1] 即可. f[i]表示以a[i]开头的最长上升子序列长度. 但这个东西难以统计.so 我们将原序列反序,求f[i] 表示以 a[i]为结尾的最长下降子序列长度即可.最后再将f.a reverse一下. 1 #include<cstdio> 2 #include<algorithm> 3

最长公共子序列——输出

首先我不得不说这道题很傻逼....你要先求公共子序列的长度......然后去DFS一遍注意要倒着搜......公共子序列也要倒着找..........我做了好久,代码: #include<bits/stdc++.h> using namespace std; char a[1001],b[1001]; int dp[1001][1001]={0}; int n1,n2,sum=0; int ans[1001]={0}; int a1[1001][101],b1[1001][101]; int

1134 最长上升子序列 (序列型 DP)

思路: 由于一般的动态规划时间复杂度是O(n^2)(哈哈哈哈 第一次用的就是这个!)用在这里由于n最大为50000 所以会超时 到这里我们可以用一个数组来动态维护这个最长上升的子序列,将你要输入的子序列一个一个按升序存入数组 如果发现当前要存入的数字x比数组最后一个还要大 那么直接存入数组,否则就将数组中按升序第一个大于x的数 用x替换掉(这里的替换我们可以用二分搜索来进行) 由于二分搜索的时间复杂度是log(n) 所以总的时间复杂度为O(n log(n) ): 下面举个例子 例如 -6 4 -

最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列. 考虑最长公共子序列问题如何分解成

动态规划的设计思想与实例(最大子段和、最长公共子序列、0-1背包、编辑距离)

动态规划算法与分治法类似,其基本思想是将总问题分解成若干个子问题,先求解子问题,再结合这些子问题的解得到原问题的解.与分治法不同的是,动态规划求解的问题经分解得到的子问题往往不是相互独立的. 基本思想: 将总问题分解成多个子问题(子问题也可以继续分解,直到无法分解),计算子问题,用一个表保存已解决的子问题的答案,算完子问题后回到总问题时从表中寻找已求得的答案,根据要求挑选最优解,加上总问题的里的具体变化再存入表中 设计步骤: 1.找出最优解的性质,并刻画其结构特征 根据具体问题找出其结构的特点,

最长公共子序列 nlogn

先来个板子 #include<bits/stdc++.h> using namespace std; const int N = 1e6+20, M = 1e6+10, mod = 1e9+7, inf = 1e9+1000; typedef long long ll; struct node { int c; int num; } u[N]; int i,j,k = 0,n,m,x,y = 0,T = 0,ans = 0,big = 0,cas = 0,num = 0,len = 0; bo

网易2017秋招笔试题3:最长公共子括号序列长度

[问题来源]网传的2017网易秋招笔试题 [问题描述] [算法思路] 下面的解题思路摘自  http://www.cnblogs.com/Atanisi/p/7500186.html 刚看到题我就想到暴力解,深搜出所有合法的括号序列,再依次比较公共子序列的长度,返回最长的.但是深搜一般和路径有关,这道题仅仅需要最大公共子序列的长度.而我们发现最大公共子序列的长度就是 s.size() - 1(当且仅当修改距离为 1 时 LCS 最大), 那么我们就想到,可以变换 s 中一个括号的位置,枚举所有的

Longest Ordered Subsequence与最少拦截系统 DP+贪心(最长上升子序列及最少序列个数)

Longest Ordered Subsequence A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence ( a1, a2, ..., aN) be any sequence ( ai1, ai2, ..., aiK), where 1 <= i1 < i2 < ... < iK <= N.