算法分析与设计--动态规划

这篇具有很好参考价值的文章主要介绍了算法分析与设计--动态规划。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文章目录

  • 一、动态规划简介
  • 二、动态规划求解步骤
  • 三、动态规划典型应用
    • 数字三角形问题
    • 最大子段和问题
    • 0-1背包问题
  • 四、最长公共子序列问题
    • 动态规划求解
  • 五、总结

前言

算法语言--java语言


一、动态规划简介

动态规划算法通常用于求解具有某种最优性质的问题。动态规划与分治算法类似,其基本思想也是将待求解的问题分解成若干个子问题,再把子问题合成一个最优解。

动态规划与分治法的区别:

分治法子问题相互独立,动态规划子问题不相互独立

动态规划问题应具备两个基本要素:

1、最优子结构性质,2、子问题重叠性质

二、动态规划求解步骤

动态规划算法适合用于求解最优化问题,通常可按以下步骤来设计:

(1)分析最优子结构性质

(2)递归地定义最优值

(3)以自底向上的方式计算出最优值

(4)根据计算最优值时得到的信息,构造最优解

三、动态规划典型应用

1、数字三角形问题

有一个群岛,共分为若干层,第1层有一个岛屿,第2层有2个岛屿,......第n层有n个岛屿。每个岛上都有一块宝,其价值是一个正整数(图中圆圈中的整数)。

寻宝者只允许从第一层的岛屿进入,从第i层的岛屿退出,不能后退,他能收集他所经过的所有岛屿上的宝贝。但是,从第i层的岛屿进入第i+1层的岛屿时,有且仅有有2条路径。你的任务是:对于给定的群岛和岛上宝贝的价值,计算一个寻宝者行走一趟所能收集宝贝的最大价值。

算法分析与设计--动态规划


 问题分析:

 这个问题抽象成三角形问题,从顶部出发,从顶至底选一条路径,使该路径经过的数字总和最大。

本题采用贪心算法就无法找到真正的最大和。当从顶部向下,使用贪心算法时,路径上的数字和为:9+15+8+9+10=51。而真正的最大和为9+12+10+18+10=59。因此本题不能使用贪心算法求最大和。

算法分析与设计--动态规划

视频讲解如下链接: 

https://www.bilibili.com/video/BV1Z94y1D7CA/?spm_id_from=333.337.search-card.all.click&vd_source=4db006022c06ce1bdafdbea04cd95cb0

动态规划法求解:

public class Main {
    public static void main(String[] args) {
    int n = 3;
        Scanner in = new Scanner(System.in);
        int[][] data = new int[n+2][n+2];
    for (int i=1;i<=n;i++){
        for (int j =1;j<=i;j++){
            int temp = in.nextInt();
            data[i][j] = MaxNum(data[i-1][j-1],data[i-1][j])+temp;//本层数加上一层两者最大的数
        }
      }
    
    //最底层的列比较大小
    int result = 0;
    for (int i=1;i<=n;i++){
        if (result<data[n][i]){
            result = data[n][i];
        }
    }
        System.out.println("最大结果为:"+result);
    }
    static int MaxNum(int a,int b){
        if (a>b){
            return a;
        }else {
            return b;
        }
    }
}

 运行如下:算法分析与设计--动态规划


2、最大子段和问题

最大子段和问题:给定n个元素的整数列(可能为负整数)a1,a2......an。求其和的最大值。

例如当(a1,a2,a3,a4,a5,a6)= (-2,11,-4,13,-5,-2),最大子段和为11-4+13=20

现在求当(a1,a2,a3,a4,a5,a6)=(11,-2,-4,13,-5,-2),最大子段和为多少?

问题分析:

动态规划求最大子段和比分治算法要简单得多!

 如子段和是大于0,则加上下一个数,如果小于0,则直接舍弃前面,加下一个数。

代码如下:

public class Main {
    public static void main(String[] args) {
        int data[] = {11,-2,-4,13,-5,-2};
        int max = MaxSum(data,6);
        System.out.println("最大子段和为:"+max);
    }
    static int MaxSum(int data[],int n){
        int a = 0;
        int max = 0;
        for (int i = 0; i < n; i++) {
            if(a>0){
                a = a+data[i];//做累加
            }else{
                a = data[i];//直接舍弃前面
            }
            if(a>max){
                max = a;
            }
        }
        return max;
    }
}

运行如下: 

算法分析与设计--动态规划


3、 0-1背包问题

给定一个物品集合S = {1,2,3...,n},物品i的重量是wi,其价值是vi,背包的容量为W,即最大载重量不能超过W。在限定的总重量W内,我们如何选择物品,才能使物品的总价值最大。

0-1背包问题样例数据
W=5 物品1 物品2 物品3 物品4
重量w 2 1 3 2
价值v 12 10 20 15

填写最优值解析:

 解法归纳:
一、如果装不下当前物品,那么前n个物品的最佳组合和前n-1个物品的最佳组合是一样的。
二、如果装得下当前物品。
假设1:装当前物品,在给当前物品预留了相应空间的情况下,前n-1个物品的最佳组合加上当前物品的价值就是总价值。
假设2:不装当前物品,那么前n个物品的最佳组合和前n-1个物品的最佳组合是一样的。
选取假设1和假设2中较大的价值,为当前最佳组合的价值。

0-1背包问题样例数据的最优值构造过程
物品\背包容量 0 1 2 3 4 5
物品1:w=2 0 0 12 12 12 12
物品2:w=1 0 10 12 22 22 22
物品3:w=3 0 10 12 22 30 32
物品4:w=2 0 10 15 25 30 37

讲解视频:

 【动态规划】背包问题_哔哩哔哩_bilibili

代码实现:

public class Text {
    public static void main(String[] args) {
        int w[] = {0,2,1,3,2};//物品重量
        int v[] = {0,12,10,20,15};//物品价值
        int bagMax = 5;//背包大小
        int dp[][] = new int[5][6];//背包问题表格
        for (int i=1;i<=4;i++){
            for (int j=1;j<=bagMax;j++){
                if(j<w[i]){
                    dp[i][j] = dp[i-1][j];
                }else {
                    dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
                }
            }
        }

        //表格的打印
        for (int i = 0;i<5;i++) {
            for (int j =0;j<6;j++){
                System.out.print(dp[i][j]+"\t\t");
            }
            System.out.println();
        }
    }
    static int max(int x,int y){
        if (x>y){
            return x;
        }else {
            return y;
        }
    }
}

运行如下:

算法分析与设计--动态规划


四、最长公共子序列问题

1、问题描述:

著名的最长公共子序列问题,即寻找序列间最大或最多公共点的问题。最长公共子序列算法的主要作用是找出两个序列中最长的公共子序列,是一种非常基础的算法,被广泛应用于程序相似性对比、图形相似处理解、计算生物学等方面。

生物学家常常利用该算法进行基因序列对比,由此推测序列的结构、功能和演化过程。

最长公共子序列问题的定义为:设有两个序列X[1:m]和Y[1:n],需要寻找它们之间的一个最长公共子序列。

例如,假设我们有如下两个序列:

X:A B C B D A B

Y:   B D C A B A

则X和Y的最长公共子序列的长度为:4

则X和Y的一个最长公共子序列为:B C B A

2、动态规划求解 

利用动态规划寻找最长公共子序列的步骤如下:

(1)先寻找最长公共子序列的长度。

(2)再通过算法从而获得最长公共子序列

根据题目得到的递推公式为: 

算法分析与设计--动态规划 

 3、代码实现

public class Text {
    static final int max = 100;
    static int[][] c = new int[max][max];
    static int[][] b = new int[max][max];

    //长度的动态规划算法
    public static int LCSLength(int m,int n,char x[],char y[]){
        for (int i=1;i<=m;i++){
            c[i][0] = 0;
        }
        for (int i=1;i<=n;i++){
            c[0][i] = 0;
        }
        for (int i = 1; i <=m; i++) {
            for (int j = 1; j <=n; j++) {
                if(x[i]==y[j]){
                    c[i][j] = c[i-1][j-1]+1;
                    b[i][j] = 1;
                }else if(c[i-1][j]>=c[i][j-1]){
                    c[i][j] = c[i-1][j];
                    b[i][j] = 2;
                }else if(c[i-1][j]<c[i][j-1]){
                    c[i][j] = c[i][j-1];
                    b[i][j] = 3;
                }
            }
        }
        return c[m][n];
    }

    //打印最长子序列
    public static void LCSL(int i,int j,char x[]) {
        if(i==0||j==0) {
            return;
        }
        if (b[i][j]==1) {
            LCSL(i - 1, j - 1, x);
            System.out.print(x[i]);
        }else if (b[i][j]==2){
            LCSL(i-1,j,x);
        }else{
            LCSL(i,j-1,x);
        }
    }
    public static void main(String[] args) {
        char x[] = {'0','A','B','C','B','D','A','B'};
        char y[] = {'0','B','D','C','A','B','A'};
        int max = LCSLength(x.length-1,y.length-1,x,y);
        System.out.println("最长公共子序列的长度为:"+max);
        System.out.print("最长公共子序列为:");
        LCSL(x.length-1,y.length-1, x);
    }
}

算法分析与设计--动态规划

 


五、总结

动态规划和分治法十分类似,主要区别为:

分治法子问题相互独立,动态规划子问题不独立。

可以使用一个表来记录所有已解的子问题的答案。

拥有最优子结构性质和子问题重叠性质的题考虑用动态规划求解。

动态规划问题需要多思考多做题才能熟能生巧,得慢慢看视频慢慢懂。文章来源地址https://www.toymoban.com/news/detail-472199.html

到了这里,关于算法分析与设计--动态规划的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法设计与分析—动态规划例题

    题目描述 求FIB数列第n项的值 输入 输入一个整数n,表示需要输出FIB数列第n项的值 输出 输出FIB数列第n项的值 样例输入  复制 样例输出  复制 提示 题目描述 长江游艇俱乐部在长江上设置了n (n=10)个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,并在下游的

    2024年04月13日
    浏览(29)
  • 【算法分析与设计】动态规划(下)

      若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的 子序列 是指 存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij 。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。   给定2个序列X和Y,当另

    2024年02月08日
    浏览(39)
  • 算法设计与分析 实验三 动态规划

    1.打家劫舍:  给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 入: 每组测试案例有两行,第一行只有一个整数N,代表着有N间房屋 第二行有N个整数,代表着每间房屋里的金额,金额范围[0, 1000]。 出:

    2024年01月24日
    浏览(63)
  • 【算法设计与分析】作业2:动态规划

    最长递增⼦序列(LIS) 编程实现求解最长递增⼦序列的三种动态规划算法(⼀些细节请参考课件) 1.1 算法1:令 L ( k ) L(k) L ( k ) 表示 s [ 1.. n ] s[1..n] s [ 1.. n ] 中以 s [ k ] s[k] s [ k ] 结尾的LIS的长度,原问题即求解 max ⁡ 1 ≤ k ≤ n L ( k ) max_{1le kle n}L(k) max 1 ≤ k ≤ n ​ L ( k

    2024年02月21日
    浏览(28)
  • 【动态规划】矩阵链乘法——算法设计与分析

    对于矩阵 U p × q U_{ptimes q} U p × q ​ 和 V q × r V_{qtimes r} V q × r ​ , Z p × r = U V Z_{ptimes r}=UV Z p × r ​ = U V ,共需计算 p q r pqr pq r 次标量乘法,时间复杂度为 Θ ( p q r ) Theta (pqr) Θ ( pq r ) 矩阵乘法满足结合律,即 ( U V ) W = U ( V W ) (UV)W=U(VW) ( U V ) W = U ( VW ) ,选择不同的结合

    2024年02月03日
    浏览(48)
  • 【动态规划】01背包问题——算法设计与分析

    若超市允许顾客使用一个体积大小为13的背包,选择一件或多件商品带走,则如何选择可以使得收益最高? 商品 价格 体积 啤酒 24 10 汽水 2 3 饼干 9 4 面包 10 5 牛奶 9 4 0-1 Knapsack Problem 输入: quad - n n n 个商品组成集合 O O O ,每个商品有属性价格 p i p_i p i ​ 和体积 v i v_i v

    2024年02月04日
    浏览(52)
  • 算法设计与分析实验:动态规划与贪心

    目录 一、零钱兑换 1.1 思路一:动态规划 1.2 思路二:贪心 二、安排工作以达到最大效益 2.1 具体思路 2.2 思路呈现 2.3 代码实现 2.4 复杂度分析 2.5 运行结果 三、雇佣k名工人的最低成本 3.1 具体思路 3.2 思路展示 3.3 代码实现 3.4 复杂度分析 3.5 运行结果 结尾语 “生活有意思的

    2024年02月19日
    浏览(38)
  • 【算法设计与分析】动态规划:数塔问题

    提示:头歌 算法作业 实验七 动态规划 第1关:数塔问题 本关任务:编写用动态规划解决数塔问题。 求解过程(自底向上) 决策结果输出过程(自顶向下) 将上述分析求解过程角标记录为 path数组 ,方便顺序输出结果 代码如下(不知题目给出三维数组的a的第三维我用处,去

    2024年02月11日
    浏览(58)
  • 【算法设计与分析】动态规划-练习题

    输入一个整数数组 S[n] ,计算其最长递增子序列的长度,及其最长递增子序列。 定义 k ( 1 ≤ k ≤ n ) k (1 ≤ k ≤ n) k ( 1 ≤ k ≤ n ) ,L[k]表示以 S[k] 结尾的递增子序列的最大长度。子问题即为 L[k]。 对于每一个k,我们都遍历前面0~k-1的所有的数,找出最大的L[i],且 S [ k ] L [

    2024年02月03日
    浏览(47)
  • 【动态规划】最长公共子序列——算法设计与分析

    子序列是给定序列中在任意位置去掉任意多个字符后得到的结果。例如: 给定序列 X X X : X : A B C B D A B X:ABCBDAB X : A BCB D A B X X X 的子序列: X 1 : A B C B D A B X_1:ABCBDAB X 1 ​ : A BCB D A B X 2 : A B C B X_2:ABCB X 2 ​ : A BCB X 3 : A C B B X_3:ACBB X 3 ​ : A CBB 给定两个序列

    2024年02月05日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包