从9.10拼多多笔试第四题产生的01背包感悟

news2024/12/27 13:15:07

文章目录

  • 题面
  • 基本的01背包问题
  • 本题变式

本文参考:

9.10拼多多笔试ak_牛客网 (nowcoder.com)

拼多多 秋招 2023.09.10 编程题目与题解 (xiaohongshu.com)

题面

拼多多9.10笔试的最后一题,是一道比较好的01背包变式问题,可以学习其解法加深对01背包问题的理解。
在这里插入图片描述
在这里插入图片描述

这是拼多多2023-9-10秋招笔试的第四题,数据量不大,甚至可以通过dfs暴力穷举写出来,每个部件只有修和换两种选择,总共就是2^N(N<=40)的复杂度,理论上来说这个复杂度是很危险的,但有题友也做出来了。当时自己也是有畏难心理,甚至没有去尝试写dfs,导致这题0分,下次多少得先尝试一下。

可是dfs终究是没那么优雅,这题其实可以巧妙地转换为背包问题。初次尝试时也确实往背包问题考虑了,但是想想一个维度为修车部件N,一个维度为修车时间M,并且题目要求无论是修还是换,这些部件全部都得处理好,也就是物品要被“全部选取”,一般的背包问题好像没法往“全部选择”这上面靠,基本思想都是在有限的容量下达成价值的最大,而选出来物品是“部分选择”出来的。

基本的01背包问题

一个基本的01背包问题如下:

在背包容量为4的情况下,选择价值最大的物品组合。

从打印的答案中也可以看出,最后只选择了15,20这两件物品。

/**
 * 每件物品只能取一次
 * @Author jiangxuzhao
 * @Description
 * @Date 2023/9/10
 */
public class bag01 {
    public static void main(String[] args) {
        // 物品价值和成本
        int[] values = {15, 20, 30};
        int[] costs = {1, 3, 4};
        // 背包最多装4
        int maxBag = 4;
        // 物品数量
        int len = costs.length;
        // dp[i][j]表示从下标为[0,i]物品中选择,放进容量为j的背包中能产生的最大价值
        // 整体空间根据物品-背包容量排开
        int[][] dp = new int[len][maxBag+1];
        // 初始化,这里maxBag+1留下maxBag=0的空间,方便偷懒递归后续背包容量,dp[0][]偷懒指定第一个物品
        // 倒序初始化保证每个物品只会被选取一次
        for (int j = maxBag; j>=0; j--){
            if (j >= costs[0]) {
                dp[0][j] = dp[0][j-costs[0]] + values[0];
            }
        }
        // 递推公式,本次物品选或者不选
        for (int i = 1; i < len; i++){
            // 倒序遍历背包容量保证每个物品只会被选取一次
            for (int j = maxBag; j>=0; j--){
                // 不选本次物品i
                dp[i][j] = dp[i-1][j];
                // 选择本次物品i
                if (j >= costs[i]) {
                    dp[i][j] = Math.max(dp[i][j], dp[i-1][j-costs[i]]+values[i]);
                }
            }
        }
        // 结果打印
        for (int i = 0; i < len; i++){
            for (int j = 0; j<=maxBag; j++){
                System.out.print(dp[i][j]+" ");
            }
            System.out.println();
        }
    }
}

本题变式

提示:这题确实也可以用01背包来做,但是需要经过一层转换。

这里需要求的是在M时间内修好自行车,再去看要的最少金钱,那么首先要检查不计成本,最少时间的情况下是否可以修好自行车,也就是将所有“换部件”的时间累加,判断是否大于M,如果不超过M,则还有降低成本的空间。

假设上面所有“换部件”的累加时间为leastTime,那么M-leastTime就是我们还能够去多花费的缓冲时间,考虑部件i,如果换成“修部件”,在原先的基础上,时间成本增加Ai - Ci,可以减少Di - Bi的成本。这其实就可以转换成01背包问题了,首先在“全部换”的基础上,起码能保证物品能够被“全部选择处理”,然后n个部件中,如果选择“修”,能够多花的总时间容量为M-t,第i个物品修理多花费的时间是Ai-Ci,能减少Di - Bi的成本,求一个“选择处理的修组合”来最大减少成本,保证花钱最少。

最终编码如下:

import java.util.Scanner;

/**
 * 输入样例
 * 1 10
 * 10 2 3 5
 * 输出样例
 * 2
 * 输入样例
 * 1 10
 * 12 2 3 5
 * 输出样例
 * 5
 * 输入样例
 * 1 10
 * 10 2 3 5
 * 输出样例
 * 2
 * @Author jiangxuzhao
 * @Description
 * @Date 2023/9/12
 */
public class Pdd_9_10_D {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int M = sc.nextInt();
        // 全部换的时间
        long leastTime = 0L;
        // 全部换的成本
        long maxCost = 0L;
        // 类比01背包,对于物品i,values[i]为可以减少的成本,costs[i]为多花费的时间
        int[] values = new int[N];
        int[] costs = new int[N];
        for(int i = 0; i < N; i++) {
            // 修时间
            int Ai = sc.nextInt();
            // 修成本
            int Bi = sc.nextInt();
            // 换时间
            int Ci = sc.nextInt();
            // 换成本
            int Di = sc.nextInt();
            leastTime += Ci;
            maxCost += Di;
            values[i] = Di - Bi;
            costs[i] = Ai - Ci;
        }
        if (leastTime > M){
            System.out.println(-1);
            return;
        }
        // 最大背包容量 = 多花费的缓冲时间
        int maxBag = (int)(M - leastTime);
        // 最大背包价值 = 选择处理的修组合最大减少成本
        long bagRes = 0L;

        long[][] dp = new long[N][maxBag+1];
        // 倒序初始化
        for(int j = maxBag; j >= 0; j--){
            if(j >= costs[0]) dp[0][j] = dp[0][j-costs[0]] + values[0];
        }
        for (int i = 1; i<N; i++){
            for (int  j = maxBag; j>=0; j--){
                // 不选当前物品
                dp[i][j] = dp[i-1][j];
                // 选当前物品
                dp[i][j] = Math.max(dp[i][j], dp[i-1][j-costs[i]]+values[i]);
            }
        }
        bagRes = dp[N-1][maxBag];
        // 最少花费的金钱
        long res = maxCost - bagRes;
        System.out.println(res);
    }
}

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

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

相关文章

手搓消息队列【RabbitMQ版】

什么是消息队列&#xff1f; 阻塞队列&#xff08;Blocking Queue&#xff09;-> 生产者消费者模型 &#xff08;是在一个进程内&#xff09;所谓的消息队列&#xff0c;就是把阻塞队列这样的数据结构&#xff0c;单独提取成了一个程序&#xff0c;进行独立部署~ --------&…

工具教程【甜心转译】-双语字幕、中文语音生成(配音),打破信息差

甜心转译 &#xff08;主站&#xff09;是一款AI加持的音/视频生成双语字幕、中文语音的软件。帮助人们更容易的获取外语信息、不管是学习、还是娱乐&#xff0c;快人一步。 主要功能 字幕生成&#xff1a;只需几个简单的步骤&#xff0c;轻松生成字幕。字幕翻译&#xff1a;…

【校招VIP】java语言考点之异常

考点介绍&#xff1a; 导致程序的正常流程被中断的事件&#xff0c;叫做异常。异常是程序中的一些错误&#xff0c;但并不是所有的错误都是异常&#xff0c;并且错误有时候是可以避免的。异常发生的原因有很多&#xff0c;通常包含以下几大类: 1.用户输入了非法数据。2.要打开的…

【Python】爬虫基础

爬虫是一种模拟浏览器实现&#xff0c;用以抓取网站信息的程序或者脚本。常见的爬虫有三大类&#xff1a; 通用式爬虫&#xff1a;通用式爬虫用以爬取一整个网页的信息。 聚焦式爬虫&#xff1a;聚焦式爬虫可以在通用式爬虫爬取到的一整个网页的信息基础上只选取一部分所需的…

首家!亚信科技AntDB数据库完成中国信通院数据库迁移工具专项测试

近日&#xff0c;在中国信通院“可信数据库”数据库迁移工具专项测试中&#xff0c;湖南亚信安慧科技有限公司&#xff08;简称&#xff1a;亚信安慧科技&#xff09;数据库数据同步平台V2.1产品依据《数据库迁移工具能力要求》、结合亚信科技AntDB分布式关系型数据库产品&…

pinduoduo(商品详情)API接口

为了进行电商平台 的API开发&#xff0c;首先我们需要做下面几件事情。 1&#xff09;开发者注册一个账号 2&#xff09;然后为每个pinduoduo应用注册一个应用程序键&#xff08;App Key) 。 3&#xff09;下载pinduoduo API的SDK并掌握基本的API基础知识和调用 4&#xff…

冠达管理:etf怎样购买?

ETF是一种指数基金&#xff0c;与传统的自动办理型基金不同&#xff0c;相比之下&#xff0c;ETF是一种被动出资东西&#xff0c;因为它们的方针是跟从某个特定的指数&#xff0c;而不是企图在市场上打败其他出资者。ETF通常具有较低的办理费用、较高的流动性和灵敏的买卖方法&…

CANoe的工作模式之争:模拟总线的两种运行方式

我们在文章《CANoe中的工作模式之争:由一段简单的代码引出的问题》中,介绍了模拟总线模式下的三种工作方式: animated with factoras fast as possibleslave mode由于模拟总线模式不需要连接真实ECU,无需和真实ECU保持时间同步,那么就可以在模拟总线上加速或放缓程序的运行…

pytorch从0开始安装

文章目录 一. 安装anaconda1.安装pytorch前需要先安装anaonda&#xff0c;首先进入官网&#xff08;Anaconda | The Worlds Most Popular Data Science Platform&#xff09;进行安装相应的版本。2.接着按如图所示安装,遇到下面这个选项时&#xff0c;选择all users.3.选择自己…

如何与 PGA Tour Superstore 建立 EDI 连接?

PGA Tour Superstore 是一家专业的高尔夫用品卖场&#xff0c;以销售高品质高尔夫球具、装备和配件为主要经营范围。其使命是为高尔夫爱好者提供一站式购物体验&#xff0c;帮助他们在球场上取得更优越的成绩。多年来&#xff0c;PGA Tour Superstore 凭借其卓越的产品选择、专…

EFCore 基于Code First开发的配置

EFCore版本&#xff1a;7.0.10 Visual Studio版本&#xff1a;2022 1、首先新建一个项目(无论是.net framework还是.net core都可以)&#xff0c;在项目中添加EFCore的程序包&#xff1a; 2、新建一个文件夹Models&#xff0c;把表模型都放在这个文件夹里 3、新建表模型&…

Java笔记:线程池

一. 正确使用ThreadPoolExecutor创建线程池 1.1、基础知识 Executors创建线程池便捷方法列表&#xff1a;下面三个是使用ThreadPoolExecutor的构造方法创建的 方法名功能newFixedThreadPool(int nThreads)创建固定大小的线程池newSingleThreadExecutor()创建只有一个线程的线…

三维模型3DTile格式轻量化压缩模型变形浅析

三维模型3DTile格式轻量化压缩模型变形浅析 在对三维模型进行轻量化压缩处理的过程中&#xff0c;常常会出现模型变形的现象。这种变形现象多数源于模型压缩过程中信息丢失或误差累积等因素。以下将对此现象进行详细分析。 首先&#xff0c;我们需要了解三维模型轻量化压缩的…

前端设计模式基础笔记

前端设计模式是指在前端开发中经常使用的一些解决问题的模式或思想。它们是经过实践证明的最佳实践&#xff0c;可以帮助我们更好地组织和管理我们的代码。 一、单例模式&#xff08;Singleton Pattern&#xff09; 单例模式是一种创建型模式&#xff0c;它保证一个类只有一个…

2023最新轻松升级、安装和试用Navicat Premium 16.2.10 教程详解

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

ArcGIS标注的各种用法和示例

标注是将描述性文本放置在地图中的要素上或要素旁的过程。 本文整理了ArcGIS中的各种标注方法、可能遇到的问题和细节,内容比较杂,想到哪写到哪。 一、正常标注某一字段值的内容 右键点击【属性】,在【标注】选项卡下勾选【标注此图层中的的要素】,在【文本字符串】栏中…

HTTPS/HTTP2

HTTPS HTTPS(HyperText Transfer Protocol Secure)&#xff0c;译为&#xff1a;超文本传输安全协议 常称为HTTP over TLS、HTTP over SSL、HTTP Secure由网景公司于1994年首次提出 HTTPS的默认端口号443&#xff08;HTTP是80&#xff09; SSL/TLS HTTPS是在HTTP的基础上使…

长胜证券:xd在股票里是什么意思?

跟着互联网的发展&#xff0c;股票市场也变得更加开放和透明。不只一般投资者能够经过在线渠道参加股票买卖&#xff0c;而且各种股票术语也成为人们日常沟通的一部分。其间一个常见的术语是“xd”&#xff0c;这个词常常被投资者和股民们运用。那么&#xff0c;xd在股票里到底…

重装系统后原git项目报错

重装系统后使用sourcetree打开项目报错提示如下&#xff1a; 解决方案就是输入上图中给的提示:

浏览器缓存机制及其分类

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 强缓存&#xff08;Cache-Control 和 Expires&#xff09;⭐ 协商缓存&#xff08;ETag 和 Last-Modified&#xff09;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几…