hdu1160--最长有序子序列

算法原理:

数组a[]为待处理数组

f[]用于记录a[]数组中,以对应位置数据为结尾的最长有序序列长度

p[]用于记录a[]数组中,以对应位置数据为结尾的前一个数据位置

使用position记录最大长度位置

以a[]={1,4,7,2,5,8,3,6,9},计算最长递增有序子序列为例

初始化f[]={1, 1, 1, 1, 1, 1, 1,1,1},p[]={0,1,2,3,4,5,6,7,8}

计算f[i]时,f[i]=max(f[j]+1) ,(其中,a[i]>a[j],i>j>=0),意思是以a[i]为结尾,找出在a[i]前比a[i]小的数据中以该数据为结尾的最大有序子序列长度max(f[j]),则以a[i]结尾的最大有序子序列长度为max(f[j])+1。计算同时定义p[i]=j,标志a[i]为结尾的最长子序列的前一个数据a[j]的位置。同时判断此时最大长度a[i]是否比当前最大长度max大,如果a[i]更大则更新position

a[]={1,4,7,2,5,8,3,6,9}

i=0  
f[]={1,1,1,1,1,1,1,1,1},  p[]={0,1,2,3,4,5,6,7,8}

i=1   f[]={1,2,1,1,1,1,1,1,1},  p[]={0,0,2,3,4,5,6,7,8}  4>1,所以最大长度为2,position=1

i=2   f[]={1,2,3,1,1,1,1,1,1},  p[]={0,0,1,3,4,5,6,7,8}  7>4,7>1 其中4结尾的长度为2,所以最大长度为3,position=2

i=3   f[]={1,2,3,2,1,1,1,1,1},  p[]={0,0,1,0,4,5,6,7,8}  2>1 所以最大长度为2

i=4   f[]={1,2,3,2,3,1,1,1,1},  p[]={0,0,1,0,1,5,6,7,8}  5>1,5>4,5>2,其中以4结尾的长度为2,所以最大长度为3

i=5   f[]={1,2,3,2,3,4,1,1,1},  p[]={0,0,1,0,1,2,6,7,8}  8比前面的数据都大,所以最大长度为4,position=5

i=6   f[]={1,2,3,2,3,4,3,1,1},  p[]={0,0,1,0,1,2,3,7,8}  3>1,3>2,其中以2结尾的长度为2,所以最大长度为3

i=7   f[]={1,2,3,2,3,4,3,4,1},  p[]={0,0,1,0,1,2,3,4,8}  6>1,6>4,6>2,6>5,6>3,其中以5结尾长度为3,所以最大长度为4

i=8   f[]={1,2,3,2,3,4,3,4,5},  p[]={0,0,1,0,1,2,3,4,5}  9比前面数据都大,所以最大长度为5,position=8

在对所有a中元素循环过后,通过max记录下最后数据位置,以及p记录的前一个数据的位置,可以递归求出LIS

#include<stdio.h>
#include<algorithm>
using namespace std;
int f[10001];
int p[10001];
struct Mouse
{
    int w;
    int s;
    int n;
} M[10001];
bool compare(const Mouse &a, const Mouse &b)
{
    if(a.w==b.w)
        return a.s > b.s;
    else
        return a.w < b.w;
}
void printLIS(int max_l)
{
    if(p[max_l]==max_l)
    {
        printf("%d\n",M[max_l].n);
        return;
    }
    printLIS(p[max_l]);
    printf("%d\n",M[max_l].n);
}
int main()
{
    int i=1,max=0,max_l=0;
    while(scanf("%d %d",&M[i].w,&M[i].s)!=EOF)
    {
        f[i]=1;
        p[i]=i;
        M[i].n=i;
        i++;
    }
    sort(M+1,M+i,compare);
    for(int k=1; k<i+1; k++)
    {
        for(int j=1; j<k; j++)
        {
            if(M[j].s>M[k].s&&M[j].w<M[k].w)
            {
                if((f[j]+1)>f[k])
                {
                    f[k]=f[j]+1;
                    p[k]=j;
                    if(f[k]>max)
                    {
                        max = f[k];
                        max_l = k;
                    }
                }
            }
        }
    }
    printf("%d\n",max);
    printLIS(max_l);
    return 0;
}
时间: 2024-09-27 10:34:30

hdu1160--最长有序子序列的相关文章

最长递增子序列(LIS)的O(N^2)与O(NlogN)算法分析

题目: 求一个一维数组arr[n]中的最长递增子序列的长度,如在序列1,5,8,3,6,7中,最长递增子序列长度为4 (即1,3,6,7). 由于LIS用O(NlogN)也能打印,O(N^2)的DP方法见最后. 从LIS的性质出发,要想得到一个更长的上升序列,该序列前面的数必须尽量的小. 对于原序列1,5,8,3,6,7来说,当子序列为1,5,8时,遇到3时,序列已经不能继续变长了.但是,我们可以通过替换,使"整个序列"看上去更小,从而有更大的机会去变长.这样,当替换5-3和替换8-6

求数组中最长递增子序列的解决方法_C 语言

存储扩展算法n2编程c 写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中的最长递增子序列的长度.例如:在序列1,-1,2,-3,4,-5,6,-7中,其最长的递增子序列为1,2,4,6 或者 -1,2,4,6.(编程之美P198-202)分析与解法根据题目的要求,求一维数组中的最长递增子序列,也就是找一个标号的序列b[0],b[1],-,b[m](0 <= b[0] < b[1] < - < b[m] < N),使得array[b[0]]<array[b[1

经典面试题:最长公共子序列

1.问题描述: 什么是最长公共子序列呢?好比一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则S 称为已知序列的最长公共子序列.     举个例子,如:有两条随机序列,如 1 3 4 5 5 ,and 2 4 5 5 7 6,则它们的最长公共子序列便是:4 5 5.     注意最长公共子串(Longest CommonSubstring)和最长公共子序列(LongestCommon Subsequence, LCS)的区别:子串(Substring)是串的一

动态规划之最长公共子序列

给定两个序列x和y,称z是x和y的公共子序列,如果z既是x的子序列,又是y的子序列:最长的公共子序列称作最长公共子序列LCS(longest common subsequence). 解题思路 (1)LCS的最优子结构 设zk是xm和yn的一个LCS,则,如果x和y的最后一个元素相同,则z中去掉最后一个元素之后zk-1仍为xm-1和yn-1的LCS. 如果xm!=yn,若zk!=xm,则z是xm-1和y的一个LCS,若zk!=yn,则z是xm和yn-1的LCS. (2)一个递归解 设c[i][j

UVa 10405:Longest Common Subsequence,最长公共子序列模板题

[链接] http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&page=show_problem&problem=1346 [原题] Problem C: Longest Common Subsequence Sequence 1: Sequence 2: Given two sequences of characters, print the length of

动态规划解最长公共子序列(LCS)问题 (附可打印LCS完整代码)

一.动态规划法 经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题.简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解的方法,问题求解耗时会按问题规模呈幂级数增加. 为了节约重复求相同子问题的时间,引入一个数组,不管它们是否对最终解有用,把所有子问题的解存于该数组中,这就是动态规划法所采用的基本方法. 二.问题:求两字符序列的最长公共字符子序列(LCS) 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的

算法系列(六)最长公共子序列(LCS)问题(连续子序列)的三种解法

最长公共子序列(LCS)问题有两种方式定义子序列,一种是子序列不要求不连续,一种是子序列 必须连续.上一章介绍了用两种算法解决子序列不要求连续的最终公共子序列问题,本章将介绍要求 子序列必须是连续的情况下如何用算法解决最长公共子序列问题. 仍以上一章的两个字符串 "abcdea"和"aebcda"为例,如果子序列不要求连续,其最长公共子序列为"abcda",如果子序列 要求是连续,则其最长公共子序列应为"bcd".在这种情况下

算法系列(五)最长公共子序列(LCS)问题(非连续子序列)的两种解法

最长公共子序列也称作最长公共子串,英文缩写是LCS(Longest Common Subsequence).其定义 是:一个序列S,如果分别是两个或多个已知序列的子序列,且是符合此条件的子序列中最长的,则称 S为已知序列的最长公共子序列. 关于子序列的定义通常有两种方式,一种是对子序列没有连 续的要求,其子序列的定义就是原序列中删除若干元素后得到的序列.另一种是对子序列有连续的要 求,其子序列的定义是原序列中连续出现的若干个元素组成的序列.求解子序列是非连续的最长公共 子序列问题是一个十分实用的

Ruby实现的最长公共子序列算法

  这篇文章主要介绍了Ruby实现的最长公共子序列算法,本文直接给出实现代码,需要的朋友可以参考下 最长公共子序列,LCS,动态规划实现. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #encoding: utf-8 #author: