动态规划算法专题(九):完全背包问题

news2024/10/28 5:52:43

目录

1. 【模板】完全背包

1.1 算法原理 

1.2 算法代码

1.3 空间优化

1.4 空间优化版本代码 

2. 零钱兑换

2.1 算法原理 

2.2 算法代码

3. 零钱兑换 II

3.1 算法原理 

3.2 算法代码

4. 完全平方数

4.1 算法原理 

4.2 算法代码


完全背包问题的初始化与 01 背包的初始时相同:

第一行需要初始化, 

第一列不需额外初始化, 在填表时一同填入即可(存在条件判定, 不会发生越界) 


1. 【模板】完全背包

【模板】完全背包_牛客题霸_牛客网

1.1 算法原理 

  • 状态表示:

dp[i][j] : 从前 i 个数中选, 总体积不超过 j , 所有选法中, 最大价值(第一问)
dp[i][j] : 从前 i 个数中选, 总体积等于 j , 所有选法中, 最大价值(第二问)

  • 状态转移方程:

dp[i][j] = max(dp[i - 1][j], dp[i][j - v[i]] + w[i])

  • 初始化

如下图.

  • 建表顺序:

从上往下每一行,
从左往右每一列 

  • 返回值

1) dp[n][V]

2) dp[n][V] == -1 ? 0 : dp[n][V]

1.2 算法代码

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt(); // 物品个数
        int large = in.nextInt(); // 背包体积
        int[] V = new int[n];
        int[] W = new int[n];
        for(int i = 0; i < n; i++) {
            V[i] = in.nextInt();
            W[i] = in.nextInt();
        }
        // 第一问
        int[][] dp = new int[n + 1][large + 1];
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j <= large; j++) {
                dp[i][j] = dp[i - 1][j];
                if(j >= V[i - 1]) dp[i][j] = Math.max(dp[i][j], dp[i][j - V[i - 1]] + W[i - 1]);
            }
        }
        System.out.println(dp[n][large]);
        // 第二问
        // 初始化
        for(int j = 1; j <= large; j++) dp[0][j] = -1;
        // 填表
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j <= large; j++) {
                dp[i][j] = dp[i - 1][j];
                if(j >= V[i - 1] && dp[i][j - V[i - 1]] != -1) 
                    dp[i][j] = Math.max(dp[i][j], dp[i][j - V[i - 1]] + W[i - 1]);
            }
        }
        System.out.println(dp[n][large] == -1 ? 0 : dp[n][large]);
    }
}

1.3 空间优化

完全背包优化时, 遍历顺序与 01 背包不同, 需从左往右遍历填表.

1.4 空间优化版本代码 

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
    /**
     * 空间优化
     * @param args
     */
    public static void main1(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt(); // 物品个数
        int large = in.nextInt(); // 背包体积
        int[] V = new int[n];
        int[] W = new int[n];
        for(int i = 0; i < n; i++) {
            V[i] = in.nextInt();
            W[i] = in.nextInt();
        }
        // 第一问
        int[] dp = new int[large + 1];
        for(int i = 1; i <= n; i++) {
            for(int j = V[i - 1]; j <= large; j++) {
                dp[j] = Math.max(dp[j], dp[j - V[i - 1]] + W[i - 1]);
            }
        }
        System.out.println(dp[large]);
        // 第二问
        // 初始化
        for(int j = 1; j <= large; j++) dp[j] = -0x3f3f3f3f;// dp[j] = -1;
        // 填表
        for(int i = 1; i <= n; i++) {
            for(int j = V[i - 1]; j <= large; j++) {
                // if(dp[j - V[i - 1]] != -1)
                dp[j] = Math.max(dp[j], dp[j - V[i - 1]] + W[i - 1]);
            }
        }
        System.out.println(dp[large] < 0 ? 0 : dp[large]);
    }
}

2. 零钱兑换

. - 力扣(LeetCode)

2.1 算法原理 

  • 状态表示:

dp[i][j]: 从前 i 个礼物中选, 体积不超过 j 的所有选法中, 最大价值
dp[i][j]: 从前 i 个硬币中选, 恰好凑成 j 的所有选法中, 最少硬币个数

  • 状态转移方程:

dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - coins[i]] + 1)

  • 初始化

只需初始化第一行.

无效状态使用 0x3f3f3f3f 表示(防止溢出)

  • 建表顺序:

从上往下每一行,
从左往右每一列

  • 返回值:

dp[n][amount] >= INF ? -1 : dp[n][amount]

2.2 算法代码

class Solution {
    public int coinChange(int[] coins, int amount) {
        int INF = 0x3f3f3f3f;
        int n = coins.length;
        int[][] dp = new int[n + 1][amount + 1];
        for(int j = 1; j <= amount; j++) dp[0][j] = INF;
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j <= amount; j++) {
                dp[i][j] = dp[i - 1][j];
                if(j >= coins[i - 1]) dp[i][j] = Math.min(dp[i][j], dp[i][j - coins[i - 1]] + 1);
            }
        }
        return dp[n][amount] >= INF ? -1 : dp[n][amount];
    }

    /**
     * 空间优化
     * @param coins
     * @param amount
     * @return
     */
    public int coinChange1(int[] coins, int amount) {
        int INF = 0x3f3f3f3f;
        int n = coins.length;
        int[] dp = new int[amount + 1];
        for(int j = 1; j <= amount; j++) dp[j] = INF;
        for(int i = 1; i <= n; i++) {
            for(int j = coins[i - 1]; j <= amount; j++) {
                dp[j] = Math.min(dp[j], dp[j - coins[i - 1]] + 1);
            }
        }
        return dp[amount] >= INF ? -1 : dp[amount];
    }
}

3. 零钱兑换 II

. - 力扣(LeetCode)

3.1 算法原理 

  • 状态表示:

dp[i][j]: 从前 i 个数中选, 能凑成 j 的选法的总数

  • 状态转移方程:

不选 i --> dp[i - 1][j]
选1个 i --> dp[i - 1][j - coins[i]]
选2个 i --> dp[i - 1][j - 2*coins[i]]
   .......

dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]]

  • 初始化

只初始化第一行, 当 j == 0 时, dp[0][0] = 1;

  • 建表顺序:

从上往下每一行,
从左往右每一列

  • 返回值:

dp[n][amount]

3.2 算法代码

class Solution {
    public int change(int amount, int[] coins) {
        int n = coins.length;
        int[][] dp = new int[n + 1][amount + 1];
        dp[0][0] = 1;
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j <= amount; j++) {
                dp[i][j] = dp[i - 1][j];
                if(j >= coins[i - 1]) dp[i][j] += dp[i][j - coins[i - 1]];
            }
        }
        return dp[n][amount];
    }
    /**
     * 空间优化
     */
    public int change1(int amount, int[] coins) {
        int n = coins.length;
        int[] dp = new int[amount + 1];
        dp[0] = 1;
        for(int i = 1; i <= n; i++) {
            for(int j = coins[i - 1]; j <= amount; j++) {
                dp[j] += dp[j - coins[i - 1]];
            }
        }
        return dp[amount];
    }
}

4. 完全平方数

. - 力扣(LeetCode)

4.1 算法原理 

  • 状态表示:

dp[i][j]: 从前 i 个物品中挑选, 容量不超过 j , 所有选法中, 最大价值(完全背包)
dp[i][j]: 从前 i 个完全平方数中挑选, 总和等于 j , 所有选法中, 最小数量

  • 状态转移方程:

不选 i*i --> dp[i - 1][j]
选1个 i*i --> dp[i - 1][j - i*i] + 1
选2个 i*i --> dp[i - 1][j - 2*i*i] + 2
 .......

dp[i][j] = min(dp[i - 1][j], dp[i][j - i*i] + 1)

  • 初始化

只初始化第一行(没有完全平方数时)

  • 建表顺序:

从上往下每一行,
从左往右每一列

  • 返回值:

dp[Math.sqrt(n)][n]

4.2 算法代码

class Solution2 {
    public int numSquares(int n) {
        int INF = 0x3f3f3f3f;
        int m = (int)Math.sqrt(n);
        int[][] dp = new int[m + 1][n + 1];
        for(int j = 1; j <= n; j++) dp[0][j] = INF;
        for(int i = 1; i <= m; i++) {
            for(int j = 0; j <= n; j++) {
                dp[i][j] = dp[i - 1][j];
                if(j - i * i >= 0) dp[i][j] = Math.min(dp[i][j], dp[i][j - i * i] + 1); 
            }
        }
        return dp[m][n];
    }

    /**
     *  空间优化
     * @param n
     * @return
     */
    public int numSquares1(int n) {
        int INF = 0x3f3f3f3f;
        int m = (int)Math.sqrt(n);
        int[] dp = new int[n + 1];
        for(int j = 1; j <= n; j++) dp[j] = INF;
        for(int i = 1; i <= m; i++) {
            for(int j = i * i; j <= n; j++) {
                dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
            }
        }
        return dp[n];
    }
}


END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2225229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电动汽车与软件定义汽车(SDV)时代的汽车行业变革

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

LeetCode437. 路径总和 III(2024秋季每日一题 50)

给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从父节点到子节点&am…

.NET Core WebApi第3讲:第一个Web Api项目

一、.NEt Core 1、运行模板项目 1&#xff09;仍然有controllers&#xff0c;说明WebApi是基于MVC模式的&#xff0c;只是对比之下这里没有MVC中的views。 因为WebApi只会向前台发送数据&#xff0c;不会向前台发送HTML页面。 2、验证模板项目的api 1&#xff09;法1&#xf…

第12次CCF CSP认证真题解

1、最小差值 题目链接&#xff1a;https://sim.csp.thusaac.com/contest/12/problem/0 100分代码&#xff1a; #include <iostream> #include <algorithm> using namespace std; int main(int argc, char *argv[]) {int n;cin >> n;int a[1010],b[1010];f…

【模型学习】

https://zhuanlan.zhihu.com/p/522344841 from transformers import AutoTokenizer tokenizer AutoTokenizer.from_pretrained(model_checkpoint) tokenizer("男女主角亦有专属声优这一模式是由谁改编的&#xff1f;", "任天堂游戏谜之村雨城") { input_…

数通自学——计算机网络基础知识IP地址、局域网、广域网、NAT、端口映射、子网掩码、网关、IPV4、IPV6

计算机网络基础知识IP地址、局域网、广域网、NAT、端口映射、子网掩码、网关、IPV4、IPV6 一、IP地址1、概念引入2、概念3、组成及分类 二、局域网和广域网1、局域网2、广域网 三、NAT与端口映射四、公网IP、私网IP五、IPV4与IPV6 一、IP地址 1、概念引入 现在思考一个问题&a…

IntelliJ IDEA 查看类class的结构Structure轮廓outline窗口, 快捷键是Alt+7

IntelliJ IDEA 查看类class的结构Structure轮廓outline窗口, 快捷键是Alt7 idea的结构Structure窗口相当于Eclipse的outline 快捷键是: Alt7 或者点击左上角主菜单面包屑,打开主菜单 然后菜单找到-视图&#xff08;View&#xff09;→ 工具窗口&#xff08;Tool Windows&…

鸿蒙开发--点击下拉菜单,同时最下面出现遮罩层的实现方法

效果展示 实现 除去最上面的Naviation标题&#xff08;房源列表&#xff09;&#xff0c;该页面有两个SearchFilter搜索筛选&#xff08;包括其中的下拉菜单&#xff09;&#xff0c;RoomList房源列表 根目录容器 显然&#xff0c;两个组件之间存在覆盖关系&#xff0c;所以…

【密码学】全同态加密张量运算库解读 —— TenSEAL

项目地址&#xff1a;https://github.com/OpenMined/TenSEAL 论文地址&#xff1a;https://arxiv.org/pdf/2104.03152v2 TenSEAL 是一个在微软 SEAL 基础上构建的用于对张量进行同态加密操作的开源Python库&#xff0c;用于在保持数据加密的状态下进行机器学习和数据分析。 Ten…

ssm旅游网页开发与设计+jsp

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 摘 要 I 目 录 III 第1章 绪论 1 1.1 研究背景 1 1.2目的和意义 1 1.3 论文研究内容 1 第2章 程序…

银河麒麟V10系统下libopenblas.so.0和libllmlmf库的安装

1、当前linux服务器系统是银河麒麟V10&#xff0c;具体的内核和cpu型号如下&#xff1a; 2、使用:uname -a来进行查询 Linux localhost.localdomain 4.19.90-89.16.v2401.ky10.x86_64 #1 SMP Sat Sep 14 13:09:47 CST 2024 x86_64 x86_64 x86_64 GNU/Linux 3、在部署QT开发的应…

vue通过JSON文件生成KML文件源码

可以使用封装的json解析器进行JSON数据获取&#xff0c;读取点的经度、维度、高程等数据&#xff0c;再使用对应的KML文件生成函数使用该源码下载KML文件&#xff08;固定KML生成&#xff1a;js模板式生成大疆上云kml文件&#xff08;含详细注释&#xff0c;已封装成函数&#…

从病理AI的基础模型发展历程,看未来的医学AI发展趋势|个人观点·24-10-23

小罗碎碎念 在临床相关的人工智能&#xff08;AI&#xff09;模型发展方面&#xff0c;传统上需要大量标注数据集&#xff0c;这使得AI的进步主要围绕大型中心和私营企业展开。所以&#xff0c;在这期推文中&#xff0c;我会介绍一些已经商用的模型&#xff0c;并且为计划进军…

Minio文件服务器:SpringBoot实现文件上传

在Minio文件服务器部署成功后(参考上篇文章Minio文件服务器&#xff1a;安装)接下来我们通过SpringBoot框架写一个接口&#xff0c;来实现文件的上传功能&#xff1a;文件通过SpringBoot接口&#xff0c;上传到Minio文件服务器。并且&#xff0c;如果上传的文件是图片类型&…

裴蜀定理与欧几里得算法——蓝桥杯真题中的应用

目录 裴蜀定理&#xff08;Bzouts Theorem&#xff09;1、定义2、推论3、欧几里得算法4、多个整数的裴蜀定理扩展 真题挑战解题思路代码实现与详细注释代码解析 裴蜀定理&#xff08;Bzout’s Theorem&#xff09; 1、定义 对于任意两个整数 a 和 b &#xff0c;如果它们的最…

Gateway 统一网关

一、初识 Gateway 1. 为什么需要网关 我们所有的服务可以让任何请求访问&#xff0c;但有些业务不是对外公开的&#xff0c;这就需要用网关来统一替我们筛选请求&#xff0c;它就像是房间的一道门&#xff0c;想进入房间就必须经过门。而请求想要访问微服务&#xff0c;就必须…

聚链成网,趣链科技参与 “跨链创新联合体”建设

近日&#xff0c;2024全球数商大会在上海举办。大会由上海数据集团和上海市数商协会联合主办&#xff0c;上海市数据局和浦东新区人民政府支持&#xff0c;以“数联全球&#xff0c;商通未来——‘链’接数字经济新未来”为主题&#xff0c;聚焦区块链技术和应用场景展开。 会上…

Windows生成公钥和私钥

1、打开命令提示符或 PowerShell&#xff1a; 按下 Win R&#xff0c;输入 cmd 或 powershell&#xff0c;然后按 Enter 打开命令提示符或 PowerShell 窗口。 2、生成密钥对&#xff1a; 输入以下命令生成 RSA 密钥对 ssh-keygen -t rsa -b 2048-t rsa 表示生成 RSA 类型的密…

开源模型应用落地-Qwen2-VL-7B-Instruct-vLLM-OpenAI API Client调用

一、前言 学习Qwen2-VL &#xff0c;为我们打开了一扇通往先进人工智能技术的大门。让我们能够深入了解当今最前沿的视觉语言模型的工作原理和强大能力。这不仅拓宽了我们的知识视野&#xff0c;更让我们站在科技发展的潮头&#xff0c;紧跟时代的步伐。 Qwen2-VL 具有卓越的图…

android studio编译错误提示无法下载仓库

一、调整方法之一 buildscript {repositories {google()jcenter()//maven { url https://maven.aliyun.com/repository/google }//maven { url https://maven.aliyun.com/repository/central }}dependencies {// classpath "com.android.tools.build:gradle:4.1.1"c…