【动态规划】最长上升子序列

题意:n个信封和1张卡片,求最多满足左信封<右信封的大小,最左边的信封能装入卡片
输入
3 3 3
5 4
12 11
9 8
输出
3
1 3 2
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

struct Node
{
    int si, sj;
    unsigned short n;
};

Node Susake[5002];

int short dp[5002][5002], b[5002], xx[5002];//path

int comp(Node a, Node b)
{
    return a.sj > b.sj ? 0 : 1;
}

int main(int argc, char *argv[])
{
    int n, si, sj, Max, fi, fj, ei, ej, k;
    while(scanf("%d%d%d", &n, &si, &sj) != EOF)
    {
        memset(Susake, 0, sizeof(Susake));
        memset(dp, 0, sizeof(dp));
        memset(b, 0, sizeof(b));
        memset(xx, 0, sizeof(xx));
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d", &Susake[i].si, &Susake[i].sj);
            Susake[i].n = i;
        }
        sort(Susake + 1, Susake + n + 1, comp);
        Max = 0;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= i; j++)
            {
                if(Susake[i].si > Susake[j].si && Susake[i].sj > Susake[j].sj &&
                   Susake[i].si > si && Susake[j].si > si &&
                   Susake[i].sj > sj && Susake[j].sj > sj)
                    dp[i][j] = b[j] + 1;
                else if(Susake[i].si <= si || Susake[i].sj <= sj)
                    dp[i][j] = 0;
                else
                    dp[i][j] = 1;
                if(b[i] < dp[i][j])
                {
                    b[i] = dp[i][j];
                    xx[i] = j;
                }
                if(Max < dp[i][j])
                {
                    ei = i; ej = j;//ei
                    Max = dp[i][j];
                }
            }
        }
        xx[1] = 1;
        if(Max)
        {
            printf("%d\n", Max);
            k = 1;
            b[k] = Susake[ei].n;
            if(Max == 1)
                printf("%d\n", b[1]);
            else
            {
                while(1)
                {
                    if(dp[ei][ej] == 1) break;
                    ei = ej;
                    ej = xx[ej];
                    k++;
                    b[k] = Susake[ei].n;
                }
                for(int i = k; i >= 2; i--)
                    printf("%d ", b[i]);
                printf("%d\n", b[1]);
            }
        }
        else printf("0\n");
    }
    return 0;
}
时间: 2024-12-17 18:30:28

【动态规划】最长上升子序列的相关文章

uva 11400 - Lighting System Design(动态规划 最长上升子序列问题变型)

本题难处好像是在于 可以把一些灯泡换成电压更高的灯泡以节省电源的钱 ,所以也才有了对最优方案的探求 好的处理方法是按照电压从小到大排序,只能让前面的换成后面的,也就满足了把一些灯泡换成电压更高的灯泡 的要求: 一种电压的灯泡,要么不换,要换则应该全换:换,说明用当前的电源不值:而既然不值则应该全部换掉以避免使用当前电源,不然即增加了灯泡费用又没节省电源费用,亏大了... 状态转移详见代码 #include<cstdio> #include<cstring> #include<

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

(1).问题描述:给出2个序列,x是从1到m,y是从1到n,找出x和y的最长公共子序列? x:A B C B D A B y:B D C A B A 则:最长公共子序列长度为4,BDAB BCAB BCBA均为LCS(最长公共子序列): 模型实现图: (2).问题解决 代码实现了最长公共子序列的长度 #include<stdio.h> #define N    10 int LCS(int *a, int count1, int *b, int count2); int LCS(int *a,

动态规划 - 最长公共子序列(LCS)

最长公共子序列也是动态规划中的一个经典问题. 有两个字符串 S1 和 S2,求一个最长公共子串,即求字符串 S3,它同时为 S1 和 S2 的子串,且要求它的长度最长,并确定这个长度.这个问题被我们称为 最长公共子序列问题. 与求最长递增子序列一样,我们首先将原问题分割成一些子问题,我们用 dp[i][j]表示 S1 中前 i 个字符与 S2 中前 j 个字符分别组成的两个前缀字符串的最 长公共子串长度. 显然的,当 i. j 较小时我们可以直接得出答案,如 dp[0][j]必 等于 0.那么,

动态规划---最长上升子序列问题(O(nlogn),O(n^2))

LIS(Longest Increasing Subsequence)最长上升子序列 或者 最长不下降子序列.很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) . ********************************************************************************* 先回顾经典的O(n^2)的动态规划算法: 设a[t]表示序列中的第t个数,dp[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设dp[

nlog(n)解动态规划--最长上升子序列(Longest increasing subsequence)

最长上升子序列LIS问题属于动态规划的初级问题,用纯动态规划的方法来求解的时间复杂度是O(n^2).但是如果加上二叉搜索的方法,那么时间复杂度可以降到nlog(n).  具体分析参考:http://blog.chinaunix.net/uid-26548237-id-3757779.html 代码: #include <iostream> using namespace std; int LIS_nlogn(int *arr, int len) { int *LIS = new int[len

动态规划 - 最长上升子序列问题

原文  http://xuanwo.org/2015/07/31/dp-lis/ 主题 动态规划 介绍 最长上升子序列问题,也就是 Longest increasing subsequence ,缩写为LIS .是指在一个序列中求长度最长的一个上升子序列的问题,是动态规划中一个相当经典问题.在这里我们可以看到,这个上升实质上就是一个对 < 进行定义的过程,所以我们求解的其实是一类问题,也就是在给定序列中求解长度最长的符合某一性质的子序列的问题.在下面总结的过程中,我还是以递增为例进行阐述. O(

动态规划——最长上升子序列

问题 最长上升子序列是一类经典的动态规划问题. 给定N个数字, A1,A2,....An,从中选择k个数字 At1, At2,... Atk,满足 1 =< t1 < t2 < .. < tk <= n,且 At1 < At2 < ... < Atk,求满足要求的最大的k. 分析 设一个动归数组dp,dp[i]表示以第i个数字(即Ai)结尾的最长上升子序列的长度,显然这种问题的划分满足无后效性和最优子结构.同时,可以很方便的推出递推关系 dp[i] = ma

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

最长公共子序列(LCS)是一类典型的动归问题. 问题 给定两个序列(整数序列或者字符串)A和B,序列的子序列定义为从序列中按照索引单调增加的顺序取出若干个元素得到的新的序列,比如从序列A中取出 A[i1], A[i2], ...A[ik],其中0=< i1 <= i2 <= ... ik <= n-1得到的新的序列 A[i1].A[i2]....A[ik]即为A的一个子序列.     两个不同的原序列A和B可能有着相同的子序列,求出A和B的公共子序列的最长长度. 分析     这种

《算法导论》读书笔记之动态规划—最长公共子序列 &amp; 最长公共子串(LCS)

From:http://my.oschina.net/leejun2005/blog/117167 1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. 2.最长公共子串 其实这是一个序贯决策问题,可以用动态规划来求解.我们采用一个二维矩阵来记录中间的结果.这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是

算法系列笔记6(动态规划—最长公共子序列/串lcs)

子序列要求元素顺序一致就可以了,而字串必须是连续的.如ABCBDAB与BDCABA两个字符串,最长公共子序列有BCBA.BDAB和BCAB, 而最长公共字串只有AB和BD<连续>.当然这里的求解只求一个,但通常是这样直接说求最长公共子串,子序列,准确的应该是之一. 最长公共子序列 法一:穷举法 检查字符串x所有字序列,共有2^m个,检查它是否在y字符串中出现,每个需要O(n),时间复杂度为指数级的. 法二:动态规划(DP) 将两个字符串x[1-m]和y[1-n]放在x轴和y轴方向上便得到一个二