• 数据结构与算法之动态规划算法(DP)


    前言

    前边我们讲过分治法,分治法的核心是将一个问题分解为n个小问题,最后合并结果。而动态规划算法的核心是穷举法,以及要寻找到一个状态方程,需要用一个DP表或者函数来记录穷举的结果,从穷举过程中选择最优的值,最后得到原始问题的解

    1.0-1背包问题

    1.1 基本概念

    完全背包问题是背包问题的一种变种,与 0-1 背包问题不同的是,每个物品可以无限次选择放入背包,即可重复使用。动态规划是解决完全背包问题的常用方法。

    1.2 具体问题

    有n个物品,每个物品的价值为Vi,重量为Wi,背包的容量为C,现在需要将n个物品放入背包,总重量不能超过背包的容量,使得装入的物品的价值达到最大。
    求解的问题:放入背包的价值最大
    约 束 条 件:重量之和不能超过背包的容量。

    实际例子: 假设物品的个数为5个,背包的容量为20,物品的价值和重量如下:

    物品编号12345
    价值v45101215
    重量w347912

    简单的例子我们可以穷举下:
    1.20=4+7+9 此时的价值为: 5+10+12=27
    2.19=7+12 此时的价值为:10+15 =25
    …等等

    1.3 c代码求解

    /**
     * 0-1 背包问题
     * @param n 物品的个数
     * @param c 背包的容量
     * @param w 物品的重量数组
     * @param v 物品的价值数组
     * @return dp表
     */
    int ** KnapsackDp(int n,int c,int *w,int *v,int ** path){
    
        int i,tempc;
        //定义一个二维的数组dp表
        int ** dp = (int **)malloc(sizeof (int*)*(n+1));
        for(int i=0;i<=n;i++){
            dp[i]= (int *)malloc(sizeof (int )*(c+1));
        }
        //由于下标是从0开始初始化第一行
        for(tempc = 0;tempc <= c ;tempc ++){
            dp[0][tempc]=0;
            path[0][tempc]=0;
        }
        for(i = 1;i <= n ;i ++){
            dp[i][0]=0;
            path[i][0]=0;
            //开始动态
            for(tempc = 1 ; tempc <= c ; tempc++){
                path[i][tempc]=0;
                if( w[i-1] <= tempc){
                    //背包的剩余重量大于物品重量
                    if(v[i-1]+dp[i-1][tempc-w[i-1]] > dp[i-1][tempc]){
                        //放入背包
                        dp[i][tempc]=v[i-1]+dp[i-1][tempc-w[i-1]];
                        path[i][tempc]=1;
                    }else{
                        dp[i][tempc]=dp[i-1][tempc];
                    }
                }else{
                    dp[i][tempc]=dp[i-1][tempc];
                }
            }
    
        }
        return dp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    1.4 测试

    int main(){
    
        int n=5;
        int c=20;
        int w[]={3,4,7,9,12};
        int v[]={4,5,10,12,15};
        //记录是否放入
        int ** path = (int **)malloc(sizeof (int*)*(n+1));
        for(int i=0;i<=n;i++){
            path[i]= (int *)malloc(sizeof (int )*(c+1));
        }
        int **dp = KnapsackDp(n,c,w,v,path);
        for (int i = 0; i <=n ; ++i) {
            for (int j = 0; j <= c ; ++j) {
                printf("%d    ",dp[i][j]);
            }
            printf("\n");
        }
        for (int i = 0; i <=n ; ++i) {
            for (int j = 0; j <= c ; ++j) {
                printf("%d    ",path[i][j]);
            }
            printf("\n");
        }
        printf("================output==================\n");
        while ( n >0 && c >0 ){
            if(path[n][c]==1){
               c = c-w[n-1];
                printf("the %d put the package!\n",n);
            }
            n--;
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    result

    2.最长公共子序列

    先看一张动态图
    lcs
    代码实现也很简单了

  • 相关阅读:
    Install CUnit test framework on ubuntu
    短视频创作有什么建议吗,如何把视频变成爆款?
    Webpack完整打包流程分析
    Git常用命令及IDEA集成Git
    Android 解析APK包
    【Nginx】负载均衡、动静分离理论篇
    Mybatis-plus多数据源单元测试@MybatisPlusTest
    在pyqt中使用yaml 实例化类
    面试突击25:sleep和wait有什么区别
    打造千万级流量秒杀第十一课 系统参数:如何按业务场景优化网络性能?
  • 原文地址:https://blog.csdn.net/qq_37400096/article/details/132752177