• 动态规划专题(一) HDU1087 最长公共子序列


    Super Jumping! Jumping! Jumping!

    首先对于动态规划问题要找出其子问题,如果找的子问题是前n个序列的最长上升子序列,但这样的子问题不好,因为它不具备无后效性,因为它的第n+1的数会影响前n个序列的长度,换句话说,如果第n+1个数加上去不一定使得和前n个数加起来就是最长子序列,具体例子很多比如5,6,1,2 第5个数是3,那么最长序列5,6加3不会比1,2加3长。

    比较好的子问题是“求以K个为终点的最长上升子序列”,其实这个子问题的好处在于它限定了一点,终点为第k个数,那么我去递推第K+1的最长子序列时,它只跟前面各个以某点为终点的最长子序列有关

    接下来,我们写出它的状态转移方程

    maxLen(k)表示为ak作为终点的最长上升子序列的长度

    初始状态:maxLen(1)=1

    maxLen(k)=max{ maxLen(i):1<=i<k且ai < ak 且k>=2}+1

    若找不到则maxLen(k)=1

    因为以小于ak为终点的各序列,若满足上述条件,加上ak,一定会形成更长的上升子序列。

    另外从认识的角度讲,ak是从终点1到k-1一个个判断下来的那么一旦他们两个是上升的,连带的会把ai的最长子序列长度带上去,使之变得更长。

    本题仅作了一个小的改动最长上升总和,思路大致相同,代码如下

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define MAXN 1005
     5 using namespace std;
     6 int num[MAXN],m[MAXN];//m记录以每个终点的最长上升总和
     7 int main()
     8 {
     9     int t,i,j,k;
    10     while(cin>>t)
    11     {
    12         if(t==0)
    13             break;
    14         memset(m,0,sizeof(0));
    15         for(i=1;i<=t;i++)
    16             scanf("%d",&num[i]);
    17         m[1]=num[1];
    18         for(i=2;i<=t;i++)
    19         {
    20             m[i]=num[i];
    21             for(j=1;j<i;j++)
    22             {
    23                 if(num[j]<num[i])
    24                     m[i]=max(m[i],m[j]+num[i]);
    25             }
    26         }
    27         k=m[1];
    28         for(i=1;i<=t;i++)
    29             k=m[i]>k?m[i]:k;
    30         cout<<k<<endl;
    31     }
    32     return 0;
    33 }
  • 相关阅读:
    python读写操作(txt, mat, xls, etc文件)
    开发linux版QQ就是支持未来的国产操作系统
    为知笔记linux绿色版的快速调用
    数学物理中的常见误区
    markdown语法小结
    信息爆炸时代的知识获取
    matlab: 数据的读写
    APS期刊投稿准备: REVTex格式
    markdown基本语法
    常见的数学关系
  • 原文地址:https://www.cnblogs.com/fancy-itlife/p/4336259.html
Copyright © 2020-2023  润新知