zoukankan      html  css  js  c++  java
  • POJ 2533简单dp

    http://poj.org/problem?id=2533

    简单的dp运用于求最长有序子序列,这里是递增

    我们假设原数列定义为数组a[],然后定义一个数组b[i],表示以a[i]结尾的最长公共子序列的长度,只要求出所有的b[i]数组也就可以确定最长的公共子序列,

                那么我们根据已经求出的b[0]--b[i-1],来求b[i]呢,,也就如何求出以a[i]结尾的最大公共子序列的长度呢,

                此时在a[0]-a[i-1]范围内,已经求出多个长度的公共子序列,且最大长度的一个序列的长度为s,这个序列的最后一个元素为t,那么

     

                1.如果a[i]<t ,那么当前最大子序列的长度为s+1,而且这个序列的最后一个元素就是a[i],即b[i]=s+1

                2.如果a[i]=t,那么这个子序列的长度不变,仍为s,b[i]=s;

                3.如果a[i]>t,这时候就会比较的麻烦了,因为a[i]不可能成为长度为s的最长公共子序列的最后一项了,然后与一个长度为s-1的公共子序列的最后一项进行比较。。直至小于某一个长度为s1的子序列的最后一个元素t1,如果a[i]仍然大于t1,那么就继续向长度更小的子序列的最后一个元素进行比较,(找寻,比较的过程中一定要同时跟已经保存好在b[i]里长度比较,这样子最后才能得到最长的)知道找到一个合适的子序列长度s2,那么此时b[i]=s2+1;如果a[i]比所有的以求子序列的最后一个元素都大话,那么最后就赋值b[i]=1;即以该元素为结尾的子序列长度为1.

                  那么如何保存这些已经查找出来的子序列的最后一一个元素呢  ,我们定义一个数组c[],即c[i]就是代表长度为i的当前最长子序列的最后一个元素,我们最终的元素超找比较就是在c[]数组中进行的,b[i]最后可以用于最终的最长子序列的输出。

     

                   按照上述的条件得到的c[i]肯定是单调递增或者递减的,如果采用二分查找的话那么时间复杂度为O(n*lgn)..

     

    动态的转移公式为:

    假设f(i)代表以a[i]结尾的最长单调自增子序列的长度:

            /    f(i-1)+1                                          , a[i]>a[i-1]

    f(i)= ---  f(i-1)                                               ,a[i]==a[i-1]

               max(max({f(j)|a[i]<a[j],i>j}+1),1)  ,a[i]<a[i-1]

     1 /*Source Code
     2 
     3 Problem: 2533        User: 297752873
     4 Memory: 168K        Time: 0MS
     5 Language: C        Result: Accepted
     6 Source Code*/
     7 #include<stdlib.h> 
     8 #include<stdio.h>
     9 #include<string.h> 
    10 int a[1000000],b[1000000],n;
    11 int LIS()
    12 {
    13     int i,j,max=0;
    14     for(i=0;i<n;i++)b[i]=1;//初始化为1,就是在所有数都比他大的情况下自成一列 
    15     for(i=1;i<n;i++)
    16     {
    17        for(j=0;j<i;j++)
    18           if(a[j]<a[i]&&b[i]<b[j]+1)//前面的保证序列的递增,后面的可以保证b[i]中保留的一定是以a[i]为结尾的最长递增序列 
    19             b[i]=b[j]+1;
    20     }
    21     for(i=0;i<n;i++)
    22     if(max<b[i])max=b[i];
    23     return max;
    24 }
    25 int main()
    26 {
    27     int i;
    28     scanf("%d",&n);
    29     for(i=0;i<n;i++)
    30     scanf("%d",&a[i]);
    31     printf("%d
    ",LIS());
    32     //system("pause");
    33     return 0;
    34 }
    View Code
  • 相关阅读:
    服务器变量 $_SERVER 详解
    PHP 函数功能参考
    ecshop后台0day漏洞原理+利用方法 XSS+Getshll
    CSRF漏洞原理说明与利用方法
    Drupal 远程命令执行漏洞(CVE-2018-7600)
    SSH登陆验证绕过漏洞(cve-2018-10933)
    单元二:建立和维护数据表
    单元一:认识数据库系统
    【 模块1 认识计算机 】1.2 认识微型计算机
    【 模块1 认识计算机 】 1.1走进计算机世界
  • 原文地址:https://www.cnblogs.com/huzhenbo113/p/3239475.html
Copyright © 2011-2022 走看看