zoukankan      html  css  js  c++  java
  • dp入门 最长公共序列,最长上升序列

    今天是看kuangbin专题12 的第一题hdu的1024最大n对子序列的最大和看不懂,就来看基础的dp最长上升序列

    1.最长公共序列

    //date:2020.4.18

    //author:lujunfeng
    /*

    状态转移方程
    dp[i][j]=0(i==0||j==0)
    =dp[i-1][j-1](i!=0&&j!=0&&s1[i]==s2[j])
    =max(dp[i-1][j],dp[i][j-1]) (s1[i]!=s2[j])

    理解:在涉及i和j判断时,不相等,就是i-1或者j-1时的最大数,相等,在i-1和j-1的时候+1

    初始状态全为0,一个小细节是存储在数组中的时候是从0开始的,所以应该判断的是i-1和j-1的下标的数组,当前的字符是否相等
    */
    #include <iostream>

    using namespace std;
    int dp[10][10];
    int main()
    {
    char s2[8]="BDCABA";
    char s1[8]="ABCBDAB";
    for(int i=0; i<=7; i++)
    for(int j=0; j<=6; j++)
    {
    if(i==0||j==0)
    dp[i][j]=0;
    else
    {
    if(s1[i-1]==s2[j-1])//因为数组是按照0开始存起的,所以需要注意,千万要注意
    dp[i][j]=dp[i-1][j-1]+1;
    else
    dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
    }
    }
    for(int i=0; i<=7; i++)
    {
    for(int j=0; j<=6; j++)
    cout<<dp[i][j]<<" ";
    cout<<endl;
    }
    cout<<dp[7][6]<<endl;
    return 0;
    }
    改进,用滚动数组处理,因为每次只是一行一行地处理,而且只与上一行有关,所以可以用一位数组,当然了,各有利弊
    #include <iostream>
    //记忆化数组,因为每一行只与上一行有关,当然了用二维数组更好理解,但是用一维数组
    //更省空间,自己举例子实现一遍就能更加理解滚动数组的过程
    using namespace std;
    int dp[10];
    int main()
    {
    char s2[8]="BDCABA";
    char s1[8]="ABCBDA";
    for(int i=0; i<=6; i++)
    for(int j=0; j<=6; j++)
    {
    if(i==0||j==0)
    dp[j]=0;
    else
    {
    if(s1[i-1]==s2[j-1])//因为数组是按照0开始存起的,所以需要注意
    dp[j]=dp[j-1]+1;
    else
    dp[j]=max(dp[j-1],dp[j]);
    }
    }

    cout<<dp[6]<<endl;
    return 0;
    }
    /*
    2.最长上升子序列,动态规划处理

    //dp(j) = { max(dp(i)) + 1, i<j且L[i]<L[j] },这个状态方程在处理的时候,还是两重循环,复杂度依然是n^2

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
    int L[7]= {5,6,7,1,2,3};
    int dp[7]= {1,1,1,1,1,1};
    cout<<"趟";
    for(int p=0; p<6; p++)
    cout<<p<<" ";
    cout<<endl;
    for(int j=0; j<6; j++)
    {
    cout<<j<<" ";
    for(int i=0; i<j; i++)
    if(L[i]<L[j]&&dp[j]<dp[i]+1)
    dp[j]=dp[i]+1;
    for(int k=0; k<6; k++)
    cout<<dp[k]<<" ";
    cout<<endl;
    }
    cout<<dp[5]<<endl;
    return 0;
    }

    输出的结果
    趟 0 1 2 3 4 5
    0  1 1 1 1 1 1
    1  1 2 1 1 1 1
    2  1 2 3 1 1 1
    3  1 2 3 1 1 1
    4  1 2 3 1 2 1
    5  1 2 3 1 2 3
    3

    贪心+二分法解决最长上升序列的问题,但是此方法的局限在于,最后只能找出最长上升子序列的长度,因为只能最后的结果表示最大可能,长度相同在于,始终在做替换操作,并没有进行移动操作,此方法的复杂度为nlogn

    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;

    const int maxn =300003, INF = 0x7f7f7f7f;
    int low[maxn];

    int n, ans;

    int binary_search(int *a, int R, int x)
    //二分查找,返回a数组中第一个>=x的位置
    {
    int L = 1, mid;
    while(L <= R)
    {
    mid = (L+R) >>1;
    if(a[mid] <= x)
    L = mid + 1;
    else
    R = mid - 1;
    }
    return L;
    }

    int main()
    {
    int a[9]= {0,3,1,2,6,4,5,10,7};
    n=8;
    low[1] = a[1];
    ans = 1; //初始时LIS长度为1
    for(int i=2; i<=n; i++)
    {
    if(a[i] > low[ans]) //若a[i]>=low[ans],直接把a[i]接到后面
    low[++ans] = a[i];
    else //否则,找到low中第一个>=a[i]的位置low[j],用a[i]更新low[j]
    low[binary_search(low, ans, a[i])] = a[i];
    }
    printf("%d ", ans); //输出答案
    for(int i=1;i<=ans;i++)
    cout<<low[i];
    return 0;
    }

  • 相关阅读:
    spring + spring mvc + mybatis + react + reflux + webpack Web
    陈忠实和路遥:日他妈的文学和你懂个锤子
    Spring+SpringMVC+MyBatis+easyUI整合基础篇
    JAVA方法中的参数用final来修饰的效果
    全球晶圆代工厂哪家强?2016年Top30名单
    EXT combobox 二级连动 清空store缓存数据
    潘通
    MySQL性能优化
    启用了不安全的HTTP方法
    Hibernate一级缓存(基于查询分析)
  • 原文地址:https://www.cnblogs.com/someonezero/p/12728964.html
Copyright © 2011-2022 走看看