D3839|完全背包

news2025/1/18 1:54:58

完全背包:

首先01背包的滚动数组中的解法是内嵌的循环是从大到小遍历,为了保证每个物品仅被添加一次。

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

而完全背包的物品是可以添加多次的,所以要从小到大去遍历,即:

// 先遍历物品,再遍历背包
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]);

    }
}

 同时找到规律,如果存在后序遍历(比如01背包的滚动数组)的话,两个for循环的顺序就不可以变,但如果都是正序的话,两个for循环的顺序就可以进行改变。


518.零钱兑换||

题解复盘:

1)dp数组的含义:dp[j]:凑成总金额j的货币组合数为dp[j]

2)数组的递推公式:dp[j] += dp[j - coins[i]];

3)初始化:

 dp[0] = 1 ;

下标非0的dp[j]初始化为0,dp[0]=1还说明了一种情况:如果正好选了coins[i]后,也就是j-coins[i] == 0的情况表示这个硬币刚好能选,此时dp[0]为1表示只选coins[i]存在这样的一种选法。

4)确定遍历顺序:

所以纯完全背包是能凑成总和就行,不用管怎么凑的。

本题是求凑出来的方案个数,且每个方案个数是为组合数。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

5)举例推导dp数组

大概的数字变化情况,coins[1]的dp[2] = coins[0]那排的dp[2] + coins[1]的dp[0],不选coins[1]的方法数加上选coins[1]的方法数.

class Solution {
    public int change(int amount, int[] coins) {
        int[] dp = new int[amount+1];
        dp[0] = 1;
        for(int i = 0;i<coins.length;i++){
            for(int j=coins[i];j<amount+1;j++ ){
                if(j-coins[i]<0){
                    dp[j] = dp[j];
                }else{
                    dp[j] = dp[j]+dp[j-coins[i]];
                }
            }
        }
        return dp[amount];
    }
}

377.组合总和IV

        这道题相较于上一道感觉是由求组合数变为了求排列数。

class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target+1];
        Arrays.sort(nums);
        if(nums[0]<target){
            dp[0] = 1;
        }else{
            dp[0] = 0;
        }
        for(int i = nums[0];i<target+1;i++){
            for(int j = 0;j<nums.length;j++){
                if(i-nums[j]>=0){
                    dp[i] = dp[i]+dp[i-nums[j]];
                }else{
                    dp[i] = dp[i];
                }
            }
        }
        return dp[target];

    }
}

70. 爬楼梯(进阶版) 

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 

每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢? 

注意:给定 n 是一个正整数

初始思路:

        之前的爬楼梯每次爬1,2个台阶,dp(3)  = dp(1)+dp(2)

        由此推断每次爬1 <= m,dp(m+1) = dp(m)+dp(m-1)+...+dp(1)

分析动态规划五部曲:

(1)dp数组的含义:dp[j] 爬j阶台阶的方法数。

(2)dp的递推公式:

dp[n] = dp[n-m]+dp[n-m+1]+...+dp[n-1];

  (3) 初始化:

        dp[1] = 1;

        dp[2] = 2;

        dp[3] = dp[2]+dp[1]+1;

        dp[4] = dp[3]+dp[2]+dp[1]+1;

dp[0] = 1;

dp[1] = dp[1]+dp[0];

dp[2] = dp[2]+dp[1]+dp[0];

(4)循环方式,先背包容量再物品,这样每一个容量都可以遍历一次所需要的物品

(5)举例:

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static int climbStairs(int n, int m) {
        int[] dp = new int[n + 1];
        Arrays.fill(dp, 0);
        dp[0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (i - j >= 0) {
                    dp[i] += dp[i - j];
                }
            }
        }
        return dp[n];
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        System.out.println(climbStairs(n, m));
    }
}

可以理解题解,但是卡码网会超时不知道为什么。


322. 零钱兑换

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

初始思路&&题解复盘:

        感觉是在完全背包的基础上变为了最少的硬币个数。之前是由小数开始遍历,如果要是最少的硬币个数感觉从大数开始遍历比较好?

动态规划五部曲:

1.dp数组的定义

       dp[j]组成j元所需要的最少硬币数

2.递归数组

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

3.初始化(这里没想到)

       dp[0] = 0;

        dp[i] = MAX_VALUE;

4.遍历顺序

       考虑到组合问题,所以先循环物品,再循环背包

        只有dp[j-coins[i]]不是初始最大值时,该位才有选择的必要

       //只有dp[j-coins[i]]不是初始最大值时,该位才有选择的必要
                if (dp[j - coins[i]] != max) {
                    //选择硬币数目最小的情况
                    dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
                }

5.推导

所以这道题目非常关键的地方一个是注意初始化,一个是只有满足条件时,该位的数值才发生更新。


279.完全平方数

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,149 和 16 都是完全平方数,而 3 和 11 不是。

初始思路:

由题意可知,这道题需要我们自己构建coins数组,如果这个数小于16,那么我们的数组就只需要装1,4,9,剩下的步骤同上一题一样,注意处理一些较少数目的特殊情况。

class Solution {
    public int numSquares(int amount) {
        if(amount<4){return amount;}
        int n = 0;
        for(int i = 0;i<amount;i++){
            if(i*i>amount){
                n=i-1;
                break;
            }

        }
        int[] coins = new int[n];
        for(int i = 0;i<coins.length;i++){
            coins[i] = (i+1)*(i+1);
        }
        int[] dp = new int[amount+1];
        dp[0] = 0;
        for(int i = 1;i<amount+1;i++){
            dp[i] = Integer.MAX_VALUE;
        }
        for(int i = 0;i<coins.length;i++){
            for(int j = coins[i];j<amount+1;j++){
                dp[j] = Math.min(dp[j],dp[j-coins[i]]+1);
            }
        }
        //System.out.println(Arrays.toString(dp));
        return dp[amount];
        
    }
}

题解复盘:

class Solution {
    // 版本一,先遍历物品, 再遍历背包
    public int numSquares(int n) {
        int max = Integer.MAX_VALUE;
        int[] dp = new int[n + 1];
        //初始化
        for (int j = 0; j <= n; j++) {
            dp[j] = max;
        }
	//如果不想要寫for-loop填充數組的話,也可以用JAVA內建的Arrays.fill()函數。
	//Arrays.fill(dp, Integer.MAX_VALUE);
	
        //当和为0时,组合的个数为0
        dp[0] = 0;
        // 遍历物品
        for (int i = 1; i * i <= n; i++) {
            // 遍历背包
            for (int j = i * i; j <= n; j++) {
                //if (dp[j - i * i] != max) {
                    dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
                //}
		//不需要這個if statement,因爲在完全平方數這一題不會有"湊不成"的狀況發生( 一定可以用"1"來組成任何一個n),故comment掉這個if statement。
            }
        }
        return dp[n];
    }
}

一个完美的递推公式:dp[j] = Math.min(dp[j], dp[j - i * i] + 1)

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

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

相关文章

在线渗透盒子,集成了近百个常见的渗透渗透工具,类似软件商城的工具可以进行工具下载

现在简单统计了一下大概有80个渗透工具左右&#xff0c;3个运行环境&#xff0c;1个破解工具 工具包介绍 该工具是一个类似软件商城的工具可以进行工具下载&#xff0c;工具的卸载&#xff0c;工具的更新&#xff0c;工具编写了自动化的安装脚本&#xff0c;不用担心工具跑不起…

oracle即时客户端(Instant Client)安装与配置

之前的文章记录了oracle客户端和服务端的下载与安装&#xff0c;内容参见&#xff1a; 在Windows中安装Oracle_windows安装oracle 如果不想安装oracle客户端&#xff08;或者是电脑因为某些原因无法安装oracle客户端&#xff09;&#xff0c;还想能够连接oracle远程服务&#…

【数据结构】递归与分治

一.递归 1.递归的概念&#xff1a; 子程序&#xff08;或函数&#xff09;. 接调用自己或通过一系列调用语句间接调用自己&#xff0c;成为递归。 递归是一种描述问题和解决问题的基本方法。 重复地把问题转化为与原问题相似的新问题&#xff0c;直到问题解决为止。 2.递归…

要参加微软官方 Copilot 智能编程训练营了

GitHub Copilot 是由 GitHub、OpenAI 和 Microsoft 联合开发的生成式 AI 模型驱动的。 GitHub Copilot 分析用户正在编辑的文件及相关文件的上下文&#xff0c;并在编写代码时提供自动补全式的建议。 刚好下周要参加微软官方组织的 GitHub Copilot 工作坊-智能编程训练营&…

Blender插件-The Grove 10 树木生长动画植物插件

注意&#xff1a;Blender和The Grove的版本匹配。 亲测Blender 2.9与The Grove 10可以配合使用&#xff0c;Blender 3.6会报错&#xff0c;具体看报错记录。 一、下载 CG咖官网地址&#xff1a; Blender插件-树木生长插件植物生成插件 The Grove 10插件资产库 CSDN下载地址…

AI技术图像编辑 Luminar Neo最新中文 for Mac

Luminar Neo是一款功能强大的AI智能图像处理工具&#xff0c;借助Luminar Neo领先的AI技术和灵活的工作流程&#xff0c;用户可以完成创意任务并获得专业品质的编辑结果。以下是该软件的主要特点和功能&#xff1a; 支持多种文件格式&#xff1a;Luminar Neo支持多种文件格式&…

Prometheus介绍和安装

Prometheus介绍和安装 1. Prometheus介绍 Prometheus&#xff08;普罗米修斯&#xff09;是一个最初在SoundCloud上构建的监控系统。自2012年成为社区开源项目&#xff0c;拥有非常活跃的开发人员和用户社区。为强调开源及独立维护&#xff0c;Prometheus于2016年加入云原生云…

N字形变换(麻烦的方法)

class Solution:def convert(self, s: str, numRows: int) -> str:#先判断z有多少隔开s_new""index_now0if len(s)<numRows or numRows1:return sfor i in range(numRows-1,-1,-1):exchange0index_exchangeindex_nows_news[index_now]#计算每一层的差距gap_but…

Git安装和使用教程,并以gitee为例实现远程连接远程仓库

文章目录 1、Git简介及安装2、使用方法2.1、Git的启动与配置2.2、基本操作2.2.1、搭建自己的workspace2.2.2、git add2.2.3、git commit2.2.4、忽略某些文件不予提交2.2.5、以gitee为例实现git连接gitee远程仓库来托管代码 1、Git简介及安装 版本控制&#xff08;Revision cont…

超好用的工具类:并发集合简介--线程安全的HashMap

超好用的工具类&#xff1a;并发集合简介 ConcurrentHashMap,这是一个搞笑的并非HashMap。你可以把它理解为一个线程安全的HashMap. CopyOnWriteArrayList,这是一个List,从名字看就知道它和ArrayList是一族的。 在读多写少的场合&#xff0c;这个List的性能非常号&#xff0c;远…

[足式机器人]Part4 南科大高等机器人控制课 CH10 Bascis of Stability Analysis

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;CLEAR_LAB 笔者带更新-运动学 课程主讲教师&#xff1a; Prof. Wei Zhang 南科大高等机器人控制课 Ch10 Bascis of Stability Analysis 1. Background1.1 What is Stability Analysis1.2 General ODE Models for Dynamic…

小程序怎么实现会员运营?

充分利用小程序快捷方便的优点&#xff0c;小程序可以融合会员机制的获客、激活、留存、转化几个大的方面。小程序会员机制其实是会员系统的获客、激活、留存和转化的机制&#xff0c;而小程序则是为会员提供注册、服务、购买的场所&#xff0c;是商家连接会员、消费者的重要途…

每日一题——轮转数组

1. 题目描述 给定一个整数数组nums&#xff0c;将数组中的元素向右轮转k个位置&#xff0c;其中k是非负数。 示例1: 输入&#xff1a;nums [1,2,3,4,5,6,7]&#xff0c;k 3 输出&#xff1a;[5,6,7,1,2,3,4] 解释&#xff1a; 向右轮转 1步&#xff1a;[7,1,2,3,4,5,6] 向右…

文字编辑软件,批量给多个文本添加文档内容

在当今信息爆炸的时代&#xff0c;文字编辑工作是很多人需要面对的&#xff0c;而怎么快速的完成编辑工作&#xff0c;则是很多人所思考解决的。现在有一款很好用的软件——首助编辑高手&#xff0c;可以批量对多个文本文档内容进行处理&#xff0c;能帮你在文字编辑的工作上节…

安装vcpkg管理opencv的安装+MFC缺失的解决

第一步&#xff0c;出现#include没有办法找到opencv头文件的问题&#xff0c;无法解决 在VC的提示下&#xff0c;安装了vcpkg&#xff0c;然后用vcpkg命令来帮助安装opencv&#xff0c;过程十分顺利。 1. cmd 到命令行窗口&#xff1b; 2. 建立src文件夹&#xff0c;并进入…

线程池构造方法的认识

线程池中构造方法的认识 文章目录 线程池中构造方法的认识corePoolSize (核心线程数)maximumPoolSize&#xff08;最大线程数&#xff09;keepAliveTime(非核心线程的空闲超时时间)TimeUnitworkQueuethreadFactoryRejectedExecutionHandler拒绝策略 标准库中提供了一个ThreadPo…

数据库编程大赛:一条SQL计算扑克牌24点

你是否在寻找一个平台&#xff0c;能让你展示你的SQL技能&#xff0c;与同行们一较高下&#xff1f;你是否渴望在实战中提升你的SQL水平&#xff0c;开阔你的技术视野&#xff1f;如果你对这些都感兴趣&#xff0c;那么本次由NineData主办的《数据库编程大赛》&#xff0c;将是…

【Oracle】修改表结构

目录 创建示例1&#xff1a;添加一个或多个列 创建示例2&#xff1a;修改列定义 创建示例3&#xff1a; 删除一列或多列 创建示例4:重命名列 创建示例5:重命名表 创建示例1&#xff1a;添加一个或多个列 -----语法&#xff1a;将新列添加到表中 ALTER TABLE table_name A…

数据权限篇

文章目录 1. 如何实现数据权限&#xff08;内核&#xff09;1.1 原理1.2 源码实现&#xff0c;mybatis如何重写sql1.2.1 重写sql1.2.2 解析sql1.2.3 DataPermissionDatabaseInterceptor 1. 如何实现数据权限&#xff08;内核&#xff09; 1.1 原理 面对复杂多变的需求&#xf…