数据结构与算法 -- 动态规划算法

1、0-1背包问题

//0-1背包问题--动态规划算法
public class DynamicPlan {

    public static void main(String[] args) {
        DynamicPlan dynamicplan = new DynamicPlan();
        int[] weight = {1, 2, 3, 4, 5};
        System.out.println("方法一     背包所装物品的重量为:" + dynamicplan.knapsack(weight, weight.length, 12));
        System.out.println("方法二     背包所装物品的重量为:" + dynamicplan.knapsack2(weight, weight.length, 12));
    }

    //方法一      weight:物品重量,n:物品个数,w:背包可承载重量
    public int knapsack(int[] weight, int n, int w) {
        boolean[][] states = new boolean[n][w+1];//默认值false
        states[0][0] = true;//第一行的数据要特殊处理,可以利用哨兵优化
        if(weight[0] <= w) {
            states[0][weight[0]] = true;
        }
        for(int i=1; i<n; i++) {//动态规划状态转移
            for(int j=0; j<=w; j++) {//不把第i个物品放入背包
                if(states[i-1][j] == true) {
                    states[i][j] = states[i-1][j];
                }
            }
            for(int j=0; j<=w-weight[i]; j++) {//把第i个物品放入背包
                if(states[i-1][j] == true) {
                    states[i][j+weight[i]] = true;
                }
            }
        }
        for(int i=w; i>=0; i--) {//输出结果
            if(states[n-1][i] == true) {
                return i;
            }
        }
        return 0;
    }

    //方法二      weight:物品重量,n:物品个数,w:背包可承载重量
    public int knapsack2(int[] weight, int n, int w) {
        boolean[] states = new boolean[w+1];//默认值false
        states[0] = true;//第一行的数据要特殊处理,可以利用哨兵优化
        if(weight[0] <= w) {
            states[weight[0]] = true;
        }
        for(int i=1; i<n; i++) {//动态规划状态转移
            for(int j=w-weight[i]; j>=0; j--) {//把第i个物品放入背包
                if(states[j] == true) {
                    states[j+weight[i]] = true;
                }
            }
        }
        for(int i=w; i>=0; i--) {//输出结果
            if(states[i] == true) {
                return i;
            }
        }
        return 0;
    }
}

2、0-1背包问题【升级版】

//0-1背包问题【升级版】--动态规划算法
public class DynamicPlan {

    public static void main(String[] args) {
        DynamicPlan dynamicplan = new DynamicPlan();
        int[] weight = {2, 2, 4, 6, 3};//物品的重量
        int[] value = {3, 4, 8, 9, 6};//物品的价值
        int n = 5;//物品个数
        int w = 9;//背包承受的最大重量
        System.out.println("背包所装物品的最大价值为:" + dynamicplan.knapsack3(weight, value, n, w));
    }

    //方法一      weight:物品重量,n:物品个数,w:背包可承载重量
    public int knapsack3(int[] weight, int[] value, int n, int w) {
        int[][] states = new int[n][w+1];
        for(int i=0; i<n; i++) {//初始化states
            for(int j=0; j<w+1; j++) {
                states[i][j] = -1;
            }
        }
        states[0][0] = 0;
        if(weight[0] <= w) {
            states[0][weight[0]] = value[0];
        }
        for(int i=1; i<n; i++) {//动态规划状态转移
            for(int j=0; j<=w; j++) {//不把第i个物品放入背包
                if(states[i-1][j] >= 0) {
                    states[i][j] = states[i-1][j];
                }
            }
            for(int j=0; j<=w-weight[i]; j++) {//把第i个物品放入背包
                if(states[i-1][j] >= 0) {
                    int v = states[i-1][j] + value[i];
                    if(v > states[i][j+weight[i]]) {
                        states[i][j+weight[i]] = v;
                    }
                }
            }
        }
        //找出最大值
        int maxValue = -1;
        for(int j=0; j<=w; j++) {
            if(states[n-1][j] > maxValue) {
                maxValue = states[n-1][j];
            }
        }
        return maxValue;
    }
}

3、"双十一"购物拼单问题

/**
 * "双十一"购物拼单问题--动态规划算法
 *
 * "双十一"购物节举办一个"满200元减50元"的促销活动,假设你女朋友的购物车中有
 * n(n>100)个想买的商品,她希望从里面选几个,在凑够满减条件的前提下,让选出来
 * 的商品价格和最大程度的接近满减条件(200元),这样就可以极大限度的"薅羊毛"
 */
public class DynamicPlan {

    public static void main(String[] args) {
        DynamicPlan dynamicplan = new DynamicPlan();
        int[] items = {12, 25, 48, 6, 33, 120, 59, 88, 4, 71, 169, 23, 112};
        dynamicplan.double11advance(items, items.length, 200);
    }

    //items 商品价格,n 商品个数,w 表示满减条件,比如200
    public void double11advance(int[] items, int n, int w) {
        boolean[][] states = new boolean[n][3*w+1];//超过3倍就没有薅羊毛的价值了
        states[0][0] = true;//第一行的数据要特殊处理
        if(items[0] <= 3*w) {
            states[0][items[0]] = true;
        }
        for(int i=1; i<n; i++) {//动态规划
            for(int j=0; j<=3*w; j++) {//不购买第i个商品
                if(states[i-1][j] == true) {
                    states[i][j] = states[i-1][j];
                }
            }
            for(int j=0; j<=3*w-items[i]; j++) {//购买第i个商品
                if(states[i-1][j] == true) {
                    states[i][j+items[i]] = true;
                }
            }
        }

        int j;
        for(j=w; j<3*w+1; j++) {
            if(states[n-1][j] == true) {
                break;//输出结果大于等于w的最小值
            }
        }
        if(j == 3*w+1) {
            return;//没有可行解
        }
        for(int i=n-1; i>=1; i--) {//i表示二维数组中的行,j表示列
            if(j-items[i] >= 0 && states[i-1][j-items[i]] == true) {
                System.out.print(items[i] + " ");//购买这个商品
                j = j - items[i];
            }//else 没有购买这个商品,j不变
        }
        if(j != 0) {
            System.out.print(items[0]);
        }
    }
}

原文地址:https://www.cnblogs.com/jiangwangxiang/p/11072573.html

时间: 2024-10-01 16:19:37

数据结构与算法 -- 动态规划算法的相关文章

数据结构与算法学习之路:背包问题的贪心算法和动态规划算法

一.背包问题描述: 有N种物品和一个重量为M的背包,第i种物品的重量是w[i],价值是p[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包重量,且价值总和最大. 二.解决方法: 1.贪心算法:贪心算法基于的思想是每一次选择都作当前最好的选择,这样最后的结果虽然不一定是最优解,但是也不会比最优解差很多. 举个例子说明可能好懂一些:一帮基友去聚餐,菜是一份一份上的,我每一次夹菜都只夹牛肉/海鲜吃,可能到最后我吃的牛肉/海鲜很多,但不一定代表我吃掉的东西的总价值最高,但是相对来说价值也很高

野生前端的数据结构练习(11)动态规划算法

一.动态规划算法 dynamic programming被认为是一种与递归相反的技术,递归是从顶部开始分解,通过解决掉所有分解出的问题来解决整个问题,而动态规划是从问题底部开始,解决了小问题后合并为整体的解决方案,从而解决掉整个问题. 动态规划在实现上基本遵循如下思路,根据边界条件得到规模较小时的解,小规模问题合并时依据递推关系式进行,也就是说较大规模的问题解可以由较小问题的解合并计算得到.最经典易懂的就是使用递归算法和动态规划算法两种不同的方式来计算斐波那契数列或求阶乘的对比,动态规划算法的特

js 高级算法 - 动态规划

主要是看了<数据结构与算法>有所感悟,虽然这本书被挺多人诟病的,说这有漏洞那有漏洞,但并不妨碍我们从中学习知识. 其实像在我们前端的开发中,用到的高级算法并不多,大部分情况if语句,for语句,swith语句等等,就可以解决了.稍微复杂的,可能会想到用递归去的解决. 但要注意的是递归写起来简洁,但实际上执行的效率并不高. 我们再看看动态规划的算法: 动态规划解决方案从底部开始解决问题, 将所有小问题解决掉, 然后合并成一个整体解决方案, 从而解决掉整个大问题 . 实例举例  (计算斐波那契数列

【算法】 算法和数据结构绪论

算法和算法分析 先说点无关紧要的.初中的时候,知道有CS这门专门的学科存在的时候最开始的概念中CS就是等同于算法.这有可能是因为当时的前桌是后来一代CS传奇WJMZBMR..因为当时看起来十分高端,再加上后来努力的方向完全和CS不搭边,所以对于算法二字一直心中抱着一种敬畏之情,觉得是整个CS中最干的干货部分.后来决定入这行之后,我的领导对我说算法这东西虽然很高大上,但是在日常工作中我们用的并不多(我们部门主要做运维和DevOps,确实对这方面的需求不大)所以也就一直耽搁着.但是随着深入,以及在网

01背包问题的动态规划算法

01背包问题我最初学会的解法是回溯法,第一反应并不是用动态规划算法去解答.原因是学习动态规划算法的时候,矩阵连乘.最长公共子串等问题很容易将问题离散化成规模不同的子问题,比较好理解,而对于01背包问题则不容易想到将背包容量离散化抽象出子问题,从情感上先入为主也误以为动态规划算法不是解决01背包问题的好方法,实际上并不是这样的.另外,动态规划算法不对子问题进行重复计算,但是要自底向上将所有子问题都计算一遍,直到计算出最终问题的结果也就是我们要的答案,有点像爬山的感觉. 问题描述:给定n种物品和一背

动态规划分析总结——如何设计和实现动态规划算法

进行算法设计的时候,时常有这样的体会:如果已经知道一道题目可以用动态规划求解,那么很容易找到相应的动态规划算法并实现:动态规划算法的难度不在于实现,而在于分析和设计-- 首先你得知道这道题目需要用动态规划来求解.本文,我们主要在分析动态规划在算法分析设计和实现中的应用,讲解动态规划的原理.设计和实现.在很多情况下,可能我们能直观地想到动态规划的算法:但是有些情况下动态规划算法却比较隐蔽,难以发现.本文,主要为你解答这个最大的疑惑:什么类型的问题可以使用动态规划算法?应该如何设计动态规划算法? 动

算法——动态规划篇——最长公共子序列

问题描述      最长公共子序列,英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列.       解决最长公共子序列,一种常用的办法,就是穷举法,组合出所有的情况,但是这样对于长序列的情况来说,是非常不实际.. 假设现在有两个序列,x[]={'A','B','C','B','D','A','B'};y[]={'B','D','C','A'

[LeetCode] 时间复杂度 O(n),空间复杂度 O(1) 的动态规划算法,题 Jump Game

Jump Game Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index. For ex

五种常用算法之二:动态规划算法

动态规划算法: 基本思想: 动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解.动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解.与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的.若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次.如果我们能够保存已解决的子问题的答案,而在需要时再找