• HZNUACM寒假集训Day6小结 线性DP


    线性DP

       考虑一组硬币面值 1,5,11 给定W,求凑出W的最少硬币个数

       我们记凑出n需要用到的最少硬币数量为f(n)   我们注意到了一个很棒的性质 : f(n)只与f(n-1) f(n-5) f(n-11) 有关。 

       更确切的说f(n)=min(f(n-1),f(n-5),f(n-11)}+1

    int f[105], cost;
    int main() {
        int n;
        scanf("%d", &n);
        f[0] = 0;
        for (int i = 1; i <= n; i++) {
            cost = INF;
            if (i - 1 >= 0) cost = min(cost, f[i - 1] + 1);
            if (i - 5 >= 0) cost = min(cost, f[i - 5] + 1);
            if (i - 11 >= 0) cost = min(cost, f[i - 11] + 1);
            f[i] = cost;
            printf("f[%d]=%d\n", i, f[i]);
        }
    }

      这个做法的原理是:

        --f(n)只与f(n-1),f(n-5),f(n-11)相关

       --我们只关心f(w)的值,不关心怎么取到W的

       这就是DP,将一个问题拆成几个子问题,分别求解这些子问题,即可推断大问题的解

       大问题的最优解可以由小问题的最优解推出,这个性质叫“最优子结构性质”。

       用DP的情况  

      --能将大问题拆成小问题

     --无后效性

     --最优子结构性质

      DP核心思想:尽量缩小可能解空间

      首先把面对的局面表示为x,称为设计状态

      对于状态x,记我们要求出的答案为f(x),目标是求出f(T)   找出f(x)与哪些局面有关,写出一个式子(称为状态转移方程)通过f(p)推出f(x)

      最长上升子序列 (LIS)

      设计状态:记f(x)为以ax结尾的LIS长度,那么答案就是max{f(x)}   

      状态转移:考虑比x小的每一个p,如果ax>af(x)可取f(p)+1

      

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    //LIS
    int n;
    int a[100], f[100];
    
    int main() {
        scanf("%d", &n);
        for (int i = 0; i < n; i++) scanf("%d", &a[i]);
        int Max;
        for (int i = 0; i < n; i++) {
            f[i] = 1;
            for (int j = 0; j < i; j++) {
                if (a[i] > a[j]) f[i] = max(f[i], f[j] + 1);
            }
            Max = max(Max, f[i]);
        }
        printf("%d", Max);
        return 0;
    }

       LCS

         

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    using namespace std;
    //LCS
    int dp[200][200];
    string x, y;
    int l1, l2;
    int main() {
        cin >> x >> y;
        int l1 = x.length();
        int l2 = y.length();
        for (int i = 1; i <=l1; i++) {
            for (int j = 1; j <=l2; j++) {
                if (x[i-1] == y[j-1]) dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        cout << dp[l1][l2];
        return 0;
    }

      洛谷P1020 导弹拦截

     1.最长不上升序列长度

     2.最长上升序列长度

     code:

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<set>
    #include<map>
    #include<cmath>
    #include<cstring>
    #include<stack>
    #include<cctype>
    const double PI = acos(-1.0);
    #define eps 1e-6
    #define INF 0x3f3f3f3f
    typedef long long ll;
    using namespace std;
    
    const int maxn = 100010;
    
    int a[maxn], d1[maxn], d2[maxn];
    int n;
    
    int main() {
        while (~scanf("%d", &a[n++]));
        int len1 = 0, len2 = 0;
        d1[0] = a[0], d2[0] = a[0];
        for (int i = 1; i < n-1; i++) {
            if (d1[len1] >= a[i]) d1[++len1] = a[i];
            else {
                d1[upper_bound(d1, d1 + len1+1, a[i], greater<int>()) - d1] = a[i];
            }
            if (d2[len2] < a[i]) d2[++len2] = a[i];
            else {
                d2[lower_bound(d2, d2 + len2+1, a[i]) - d2] = a[i];
            }
        }
        //for (int i = 0; i < len1; i++) printf("%d ", d1[i]);
        //for (int i = 0; i < len2; i++) printf("%d ", d2[i]);
        printf("%d\n%d", len1 + 1, len2 + 1);
        return 0;
    }
    View Code

      

  • 相关阅读:
    JDBC连接效率问题
    如何配置Filter过滤器处理JSP中文乱码(转)
    Servlet生命周期与工作原理(转)
    ANR触发原理
    SystemServer概述
    Zygote总结
    ART、JIT、AOT、Dalvik之间有什么关系?
    谈谈android缓存文件
    Activity启动过程全解析
    tombstone问题分析
  • 原文地址:https://www.cnblogs.com/hznumqf/p/12256069.html
Copyright © 2020-2023  润新知