zoukankan      html  css  js  c++  java
  • 动态规划(最长公共序列,最长上升序列)

    在牛客网上刷面经的过程中,发现面试常问的两道题,这里记录下来,方便以后复习查看。

    并分别在 poj  1458   2533   AC!

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define N 1005
    using namespace std;
    int dp[N][N];
    
    /*
        dp[i][j]表示 P1[1...i]与 P2[1...j]的最长公共子序列LCS 
        初始状态:某一个排列为空,那么LCS肯定为0,故很容易推断出 dp[0][1..n]=0, dp[1..n][0] 
        1、if P1[n]==P2[n],则 dp[n][n]=dp[n-1][n-1] + 1
        2、if P1[n]!=P2[n], 则 dp[n][n] = max(dp[n][n-1], dp[n-1][n]) 
        
        Tips: 
        为了提高效率,采用自底向上计算的方法。
        也即先计算dp[1][1]... 最后计算dp[n][n],因为dp[n][n]肯定要用到之前的状态嘛
    */
    
    int solve(string p1, string p2, int p1_len, int p2_len){
        for(int i=1;i<=p1_len;i++){
            for(int j=1;j<=p2_len;j++){
                if(p1[i-1]==p2[j-1]){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }else{
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
                }
            }
        }
        return dp[p1_len][p2_len];
    }
    int main(){
        string p1, p2;
        while(cin>>p1>>p2){
            memset(dp, 0, sizeof(dp));
            int p1_len = p1.length();
            int p2_len = p2.length();
            cout<<solve(p1, p2, p1_len, p2_len)<<endl;
        }
        return 0;
    }
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define N 1005
    using namespace std;
    int p1[N];
    int n; 
    int dp[N];
    /*
        dp[i]表示 P[0...i] 的最长上升子序列 LIS 代码中solve_1
        方法一 : 直接dp,O(n^2)
            1、dp[0] = 1 
            2、dp[i] = max(dp[i], dp[j]) + 1, 0<=j<i, P[i]>P[j](因为只有大于才是上升的序列) 
        
        方法二 :贪心 + 二分,O(nlogn) 代码中solve_2 
            贪心:对于固定某一长度LIS而言,最后一个数字越小,越有可能添加新元素 
                  如长度为2的LIS{1,2}比{1,3}好! 
            1、我们维护一个dp数组, dp[i]表示P[0..i]这个长度为i+1的序列 LIS最小值
            2、利用二分查找找到位置,并插入之 
            3、最后结果即为dp数组的长度 
    */
    int solve_1(int p1[], int p1_len){
        int ans = 0;
        for(int i=0;i<p1_len;i++){
            dp[i]=1;
        }
        for(int i=0;i<p1_len;i++){
            for(int j=0;j<i;j++){
                if(p1[i]>p1[j])
                    dp[i] = max(dp[i], dp[j]+1);
            }
            ans = max(ans, dp[i]);
        }
        return ans;
    }
    
    int solve_2(int p1[], int p1_len){
        int pos = 0;
        dp[0]=p1[0];
        for(int i=1;i<p1_len;i++){
            if(p1[i]>dp[pos]){
                dp[++pos] = p1[i];
            }else{
                int *idx = lower_bound(dp, dp+pos+1, p1[i]);
                //cout<<*idx<<endl;
                dp[idx-dp] = p1[i];
            }
        }
        return pos+1;
    }
    int main(){ 
        cin>>n;
        for(int i=0;i<n;i++){
            int m;cin>>m;
            p1[i]=m;
        }
        //cout<<solve_1(p1, n)<<endl;
        cout<<solve_2(p1, n)<<endl;
        return 0;
    }
  • 相关阅读:
    Pytorch安装
    使用Inception-v3进行图像分类
    Tensorflow模型保存与载入
    LSTM用于MNIST手写数字图片分类
    卷积神经网络应用于MNIST数据集分类
    手工设计神经MNIST使分类精度达到98%以上
    关于优化器的选择
    手动设计神经网络进行MNIST分类
    Matplotlib学习
    Apiview使用方法
  • 原文地址:https://www.cnblogs.com/logo-88/p/11445436.html
Copyright © 2011-2022 走看看