代码随想录打卡—day44—【DP】— 8.28 完全背包基础

news2024/11/27 9:55:46

1 完全背包基础

完全背包和01背包问题唯一不同的地方就是,每种物品有无限件

完全背包的物品是可以添加多次的,所以要内嵌的背包容量循环从小到大去遍历,即:(至于为什么,内嵌背包容量循环从小到大遍历就可以实现物体被添加多次的,见解释)

// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = weight[i]; j <= bagWeight ; j++) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

    }
}

 并且,对于纯完全背包问题,其for循环的先后循环是可以颠倒的!

2 518. 零钱兑换 II + 322. 零钱兑换

518. 零钱兑换 II

根据上面学的理论,一次AC代码:

class Solution {
public:
    int dp[5005];   // 能正好装满i的背包的方式数目
    /*
    dp[j] += dp[j - coins[i]];
    dp[0] = 1;
    i++ j++
    模拟——
    */

    int change(int amount, vector<int>& coins) 
    {
        dp[0] = 1;

        for(int i = 0; i < coins.size(); i++)
            for(int j = 0; j <= amount; j++)
                if(j >= coins[i])dp[j] += dp[j - coins[i]];

        return dp[amount];
    }
};
  • 讨论1:

首先dp[0]一定要为1,dp[0] = 1是 递归公式的基础。如果dp[0] = 0 的话,后面所有推导出来的值都是0了。dp[0]=1还说明了一种情况:如果正好选了coins[i]后,也就是j-coins[i] == 0的情况表示这个硬币刚好能选,此时dp[0]为1表示只选coins[i]存在这样的一种选法。

  • 讨论2:两个for谁外谁内嵌的讨论(组合or排列)

在动态规划:关于完全背包,你该了解这些! (opens new window)中讲解了完全背包的两个for循环的先后顺序都是可以的。但本题就不行了!

本题,两个for循环的先后顺序可就有说法了。

  • 我们先来看 外层for循环遍历物品(钱币),内层for遍历背包(金钱总额)的情况。
for (int i = 0; i < coins.size(); i++) { // 遍历物品
    for (int j = coins[i]; j <= amount; j++) { // 遍历背包容量
        dp[j] += dp[j - coins[i]];
    }
}

假设:coins[0] = 1,coins[1] = 5。

那么就是先把1加入计算,然后再把5加入计算,得到的方法数量只有{1, 5}这种情况。而不会出现{5, 1}的情况。

所以这种遍历顺序中dp[j]里计算的是组合数!

  • 如果把两个for交换顺序,代码如下:
for (int j = 0; j <= amount; j++) { // 遍历背包容量
    for (int i = 0; i < coins.size(); i++) { // 遍历物品
        if (j - coins[i] >= 0) dp[j] += dp[j - coins[i]];
    }
}

背包容量的每一个值,都是经过 1 和 5 的计算,包含了{1, 5} 和 {5, 1}两种情况。

此时dp[j]里算出来的就是排列数!

可能这里很多同学还不是很理解,建议动手把这两种方案的dp数组数值变化打印出来,对比看一看!(实践出真知)


我在pad上模拟了一下,就能发现由于先背包后物体这样的循环方式会已经考虑了一次nums[i = 0...nums.size()-1]之后又反复考虑合法的nums[i = 0...nums.size()-1] 就会出现譬如除了[1,1,2]又算一次[1,2,1]这样的情况。所以如果以后又不明白可以看下图,或者再模拟一次,自然就发现这个现象了。


322. 零钱兑换

类似的一题:

class Solution {
public:
    long long dp[10005];   // 能正好装满i的背包的最少硬币个数
    /*
        dp[j] = min(dp[j],dp[j - coins[i]] + 1)
                    不装i  装i
        dp[0] = 0;
        其他非0下标初始化为INT_MAX
        i++ j++
        模拟——
        0 1 2 3 4 5 6 7 8 9 10 11 
        0 1 1 2 2 3 3 4 4 5 5 6 
        0 1 1 2 2 1 2 2 3 3 2 3 
    */

    int coinChange(vector<int>& coins, int amount) 
    {
        dp[0] = 0;
        for(int i = 1; i <= amount; i++)dp[i] = INT_MAX;

        for(int i = 0; i < coins.size(); i++)
        {
            for(int j = 0; j <= amount; j++)
                if(j >= coins[i])dp[j] = min(dp[j],dp[j - coins[i]] + 1);

            // for(int j = 0; j <= amount; j++)cout << dp[j] << ' ';
            // cout << endl;
        }

        if(dp[amount] == INT_MAX)return -1;
        else return dp[amount];
    }
};

3 377. 组合总和 Ⅳ

377. 组合总和 Ⅳ

大家在公众号里学习回溯算法专题的时候,一定做过这两道题目回溯算法:39.组合总和 (opens new window)和回溯算法:40.组合总和II (opens new window)会感觉这两题和本题很像!

但其本质是本题求的是排列总和,而且仅仅是求排列总和的个数,并不是把所有的排列都列出来。

如果本题要把排列都列出来的话,只能使用回溯算法爆搜

求给定背包容量,装满背包有多少种方式 + 组合问题。AC代码:

class Solution {
public:
    long long dp[1010];  //容积为i的背包装满时候 不同装载方式的排列数
    /*
    和零钱兑换很像
    dp[j] += dp[j - nums[i]]

    dp[0] = 1

    先背包容量j++ 后物体i++

    模拟:

    */

    int combinationSum4(vector<int>& nums, int target) {
        dp[0] = 1;

        for(int j = 0; j <= target; j++)
        {
            for(int i = 0; i < nums.size();i++)
            {
               // if(j >= nums[i] && dp[j])  // 一直过不了的写法 应该是两个数相加爆int但是我开了long long 还这个错而不是答案错误 见鬼了
                if(j >= nums[i] && dp[j] + dp[j - nums[i]] <= INT_MAX )  
                    dp[j] = (long long)(dp[j] + dp[j - nums[i]]);
            }
        }
        return dp[target];
    }
};

有个坑:C++测试用例有两个数相加超过int的数据,所以需要在if里加上dp[i] < INT_MAX - dp[i - num]。但我开了long long 那个地方还是一样的报错,见鬼了

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

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

相关文章

mysql 计算两点之间距离

先说一下我们可能会用到的一些场景&#xff0c;这样同学们可以先评估&#xff0c;该篇文章是否对你有帮助&#xff01; 场景&#xff1a; 假设 美团&#xff0c;我点外卖时&#xff0c;系统会让我先进行定位&#xff0c;比如我定位在了 A 点&#xff0c;系统就会给我推荐&…

八路参考文献:[八一新书]许少辉.乡村振兴战略下传统村落文化旅游设计[M]北京:中国建筑工业出版社,2022.

八路参考文献&#xff1a;&#xff3b;八一新书&#xff3d;许少辉&#xff0e;乡村振兴战略下传统村落文化旅游设计&#xff3b;&#xff2d;&#xff3d;北京&#xff1a;中国建筑工业出版社&#xff0c;&#xff12;&#xff10;&#xff12;&#xff12;&#xff0e;

多商户门店会员卡充值收款营销公众号开发

多商户门店会员卡充值收款营销公众号开发 一、功能特色&#xff1a; 专注于收款码支持商户入驻功能&#xff0c;降低运营成本资金可以直接到达商户&#xff0c;支持微信分账方式分配佣金&#xff0c;完全符合支付结算相关法规充值、充次支持给赠值设置有效期&#xff0c;促进…

防雷浪涌保护器选型方案

防雷浪涌保护器是一种用于保护电气设备免受雷电或其他电源干扰引起的过电压或过电流的装置。防雷浪涌保护器的选型应根据国家标准、设备要求和实际工程条件进行&#xff0c;以达到既满足防雷验收要求&#xff0c;又能有效保护设备的目的。地凯科技介绍一些常用的防雷浪涌保护器…

论文解读 | OmniObject3D:用于逼真感知、重建和生成的大词汇量3D对象数据集

原创 | 文 BFT机器人 这篇论文的主要目标是介绍和探索OmniObject3D数据集&#xff0c;该数据集包含大量真实扫描的3D物体&#xff0c;涵盖了190个类别&#xff0c;提供了多种丰富的注释&#xff0c;包括纹理3D网格、采样点云、多视图图像等。作者将OmniObject3D应用于多个3D视…

mysql和mybatisPlus实现:datetime类型的字段范围查询

前提说明 数据库在存储数据时,我们为了精确一下时间,便会把改时间类型的字段设置为datetime类型; 在过滤数据库数据时,我们又需要对该字段进行一个范围的过滤 由此,便出现了这篇博客 datetime数据类型 在MySQL中,datetime数据类型用于保存日期和时间的值。它的格式为Y…

ChatGPT 制作可视化柱形图突出显示第1名与最后1名

对比分析柱形图的用法。在图表中显示最大值与最小值。 像这样的动态图表的展示只需要给ChatGPT,AIGC,OpenAI 发送一个指令就可以了, 人工智能会快速的写出HTML与JS代码来实现。 请使用HTML,JS,Echarts完成一个对比分析柱形图,在图表中突出显示第1名和最后1名用单独一种不…

局域网远程软件Radmin

Radmin是一个快速且安全的远程控制和远程访问软件&#xff0c;通过它可以就像坐在远程计算机前一样&#xff0c;在远程计算机上工作&#xff0c;并可以从多个位置访问远程计算机。&#xff08;本例使用的版本是Radmin 3.5&#xff09; 下载Radmin 3.5安装包。 Radmin 3.5安装…

通信原理板块——基础知识(三)

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 7、能量信号的频谱密度 (1)能量信号…

直播时代下的海外网红营销:挑战与机遇并存

随着科技的迅猛发展&#xff0c;互联网正在以前所未有的速度改变着人们的生活方式和商业模式。其中&#xff0c;直播和网红营销作为数字时代的新生力量&#xff0c;迅速崛起并引领着市场的潮流。特别是在海外市场&#xff0c;直播时代为海外网红营销带来了前所未有的机遇和挑战…

ThinkPHP 通用的API格式封装

ThinkPHP 通用的API格式封装 1.创建status.php 用于设置通用的状态码返回枚举类2.将API返回格式统一封装3.重写BaseController中的__call方法4.在控制器下面新建Error控制器&#xff0c;然后添加__call方法 1.创建status.php 用于设置通用的状态码返回枚举类 <?phpreturn[…

[Agent]开发---ConversationalRetrievalAgent开发

参考资料[langchain官方文档]&#xff1a; tool retrieval agent::::https://python.langchain.com/docs/modules/agents/how_to/custom_agent_with_tool_retrieval retrieval memory:::https://python.langchain.com/docs/modules/memory/types/vectorstore_retriever_memory …

科技巨擘:探索中国机器人产业的腾飞之路

原创 | 文 BFT机器人 引言 今年4月&#xff0c;特斯拉宣布在德州建造全球最大的电池工厂&#xff0c;这一举措进一步实现了马斯克对于“机器制造机器”的大目标。这座工厂不像过去依靠传统的工人模式&#xff0c;而是采用大量机器人完成生产任务。 机器人已成「刚需」。 机器人…

Mybatis小记

目录 Mybatis第一个程序 xml文件 测试类 错误排查 Mybatis第一个程序 1.搭建实验数据库 2.导入MyBatis相关jar包 3.编写MyBatis核心配置文件 4.编写MyBatis工具类 5.创建实体类、 6.编写Mapper接口类 7.编写Mapper.xml配置文件 8.编写测试类 对象传参只引用需要的属性就可…

突破连接壁垒,火山引擎边缘云网络的先行之路

在万物互联时代&#xff0c;信息不局限于人与人之间的交流&#xff0c;大量的机器设备也需要进行信息交流。就在去年&#xff0c;我国率先迎来了“物超人”的历史性时刻&#xff0c;即物联网连接数超越了人联网连接数。边缘云的发展进入到“黄金十年”。 “要致富&#xff0c;…

多线程(一)

一.什么是线程 一个线程就是一个执行流&#xff0c;多个线程就是多个执行流&#xff0c;多线程就是让多个执行流分别执行自己的代码。 比如&#xff1a;利用多线程在控制台上循环交替打印A和B package demo; public class Main {static class SubThread extends Thread{Over…

Webgl利用缓冲区绘制三角形

什么是attribute 变量 它是一种存储限定符&#xff0c;表示定义一个attribute的全局变量&#xff0c;这种变量的数据将由外部向顶点着色器内传输&#xff0c;并保存顶点相关的数据&#xff0c;只有顶点着色器才能使用它 <!DOCTYPE html> <html lang"en"&g…

Blender界面学习02

学习视频 【基础篇】1.3 认识界面_哔哩哔哩_bilibili 基本的3d建模的流程是什么&#xff1f; 四个角现出加号时可以拆分窗口&#xff0c;也可以合并窗口 向自己的方向拉是合并&#xff0c;向不是自己的方向拉是合并 如果界面搞乱后需要回到原来的布局 然后在新建的布局上右击 …

CSRF漏洞场景复现

文章目录 CSRF漏洞是什么&#xff1f;场景复现get方式攻击post方式攻击 原理分析 CSRF漏洞是什么&#xff1f; 跨站请求伪造(Cross Site Request Forgery&#xff0c;CSRF)是一种攻击&#xff0c;它强制浏览器客户端用户在当前对其进行身份验证后的Web 应用程序上执行非本意操作…

手把手教你用R优雅地绘制研究区地图

用R语言绘制研究区图和地图 引言 在地理信息系统和数据可视化领域&#xff0c;绘制研究区图和地图是非常重要的任务。R语言是一种功能强大的统计分析和可视化工具&#xff0c;也可以用于绘制各种类型的地图。本文将介绍如何使用R语言绘制研究区图和地图。 准备工作 在使用R语…