当前位置: 首页 > news >正文

第十三届蓝桥杯JavaB组国赛G题——背包与魔法 (AC)

目录

  • 1.背包与魔法
    • 1.问题描述
    • 2.输入格式
    • 3.输出格式
    • 4.样例输入
    • 5.样例输出
    • 6.数据范围
    • 7.原题链接
  • 2.解题思路
  • 3.Ac_code

1.背包与魔法

1.问题描述

  小蓝面前有 N N N 件物品, 其中第 i i i 件重量是 W i W_{i} Wi, 价值是 V i V_{i} Vi 。她还有一个背包, 最大承重是 M M M

  小蓝想知道在背包称重范围内, 她最多能装总价值多少的物品?

  特别值得一提的是, 小蓝可以使用一个魔法 (总共使用一次), 将一件物品 的重量增加 K K K, 同时价值翻倍。(当然小蓝也可以不使用魔法)

2.输入格式

第一行包含 3 个整数 N 、 M N 、 M NM K K K

以下 N N N 行, 每行两个整数 W i W_i Wi V i V_i Vi

3.输出格式

一个整数代表答案。

4.样例输入

3 10 3
5 10
4 9
3 8

5.样例输出

26

6.数据范围

1 ≤ N ≤ 2000 , 1 ≤ M , K ≤ 10000 , 0 ≤ W i , V i ≤ 10000 1 \leq N \leq 2000,1 \leq M, K \leq 10000,0 \leq W_{i}, V_{i} \leq 10000 1N2000,1M,K10000,0Wi,Vi10000

7.原题链接

背包与魔法

2.解题思路

  首先,想解决此题的前置知识是需要掌握普通的 01 01 01背包问题,当然这题肯定不可能这么简单。题目相对于 01 01 01背包来说,唯一的区别仅仅在于小蓝可以使用 1 1 1次魔法。我们只需要多加一维状态记录是否使用了魔法即可,下面考虑 d p dp dp状态。

   f [ i ] [ j ] [ 0 ] f[i][j][0] f[i][j][0]:表示只考虑前 i i i个物品,背包容量为 j j j,并且还没有使用魔法的情况下的最大价值。我们考虑对该状态进行转移,因为这一状态是未使用魔法的,所以转移方程同 01 01 01背包一样。
f [ i ] [ j ] [ 0 ] = { f [ i − 1 ] [ j ] [ 0 ] 当  j < w [ i ] m a x ( f [ i − 1 ] [ j ] [ 0 ] , f [ i − 1 ] [ j − w [ i ] ] [ 0 ] ) 当  j > = w [ i ] f[i][j][0] = \begin{cases} f[i-1][j][0] &\text{当 $j<w[i]$}\\ max(f[i-1][j][0],f[i-1][j-w[i]][0]) &\text{当 $j>=w[i]$}\\ \end{cases} f[i][j][0]={f[i1][j][0]max(f[i1][j][0],f[i1][jw[i]][0]) j<w[i] j>=w[i]

   f [ i ] [ j ] [ 1 ] f[i][j][1] f[i][j][1]:表示只考虑前 i i i个物品,背包容量为 j j j,并且已经使用了魔法 (注意并不一定是对第 i i i个物品使用) 的情况下的最大价值。考虑每个背包的选择情况的,我将其分为三种情况考虑。

  1. 对于当前物品 i i i,如果满足 w [ i ] > j w[i]>j w[i]>j,那么说明该物品无法选择,更不用考虑是否对该物品使用魔法
  2. 如果在不符合情况 1 1 1的情况下,此时满足 w [ i ] + k > j w[i]+k>j w[i]+k>j,那么我们是无法对该背包使用魔法的,因为使用以后物品重量超过了背包重量,但我们是可以在不使用魔法的情况下选择该物品
  3. 如果此时满足 w [ i ] + k < = j w[i]+k<=j w[i]+k<=j那么说明我们可以使用魔法选择该物品。
  4. 对三种情况进行细讲,首先第一种,因为根本选不了背包,所以状态转移只有一种情况。对于第二种情况,虽然我们可以选择此物品,但我们也可以不选择它,两者情况取最大值。对于第三种情况,我们可以不选它,也可以选它,也可以使用魔法选它,存在三种情况,我们三种情况取最大值。这里需要注意的是,当我们对该背包使用魔法时,转移时应该是前面没有使用魔法的状态,即最后一维状态是 0 0 0,因为魔法只能用一次
    状态转移
    f [ i ] [ j ] [ 1 ] = { f [ i − 1 ] [ j ] [ 1 ] 1 m a x ( f [ i − 1 ] [ j − w [ i ] ] [ 0 ] + v [ i ] , f [ i ] [ j ] [ 0 ] ) 2 m a x ( m a x ( f [ i ] [ j ] [ 1 ] , f [ i − 1 ] [ j − w [ i ] ] [ 1 ] + v [ i ] ) , f [ i − 1 ] [ j − ( w [ i ] + k ) ] [ 0 ] + v [ i ] ∗ 2 ) 3 f[i][j][1]= \begin{cases} f[i-1][j][1] &\text{1}\\ max(f[i-1][j-w[i]][0]+v[i],f[i][j][0]) &\text{2}\\ max(max(f[i][j][1],f[i-1][j-w[i]][1]+v[i]),f[i-1][j-(w[i]+k)][0]+v[i]* 2) &\text{3}\\ \end{cases} f[i][j][1]= f[i1][j][1]max(f[i1][jw[i]][0]+v[i],f[i][j][0])max(max(f[i][j][1],f[i1][jw[i]][1]+v[i]),f[i1][j(w[i]+k)][0]+v[i]2)123

  因为问题本质还是属于 01 01 01背包问题,所以我们可以使用滚动数组进代码进行时间复杂度和空间复杂的优化,压缩一维状态,状态转移可以写成:
f [ i ] [ 1 ] = { m a x ( f [ j − w [ i ] ] [ 0 ] + v [ i ] , f [ j ] [ 0 ] ) m a x ( m a x ( f [ j ] [ 1 ] , f [ j − w [ i ] ] [ 1 ] + v [ i ] ) , f [ j − ( w [ i ] + k ) ] [ 0 ] + v [ i ] ∗ 2 ) f[i][1]= \begin{cases} max(f[j-w[i]][0]+v[i],f[j][0]) &\text{}\\ max(max(f[j][1],f[j-w[i]][1]+v[i]),f[j-(w[i]+k)][0]+v[i]* 2) &\text{}\\ \end{cases} f[i][1]={max(f[jw[i]][0]+v[i],f[j][0])max(max(f[j][1],f[jw[i]][1]+v[i]),f[j(w[i]+k)][0]+v[i]2)

3.Ac_code

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Scanner;

public class Main {
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static int N=2010,M=10010;
    static int[] w=new int[N];
    static int[] v=new int[N];
    static long[][] f=new long[M][2];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int k = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            w[i] = sc.nextInt();
            v[i] = sc.nextInt();
        }
        for (int i = 1; i <= n; i++) {
            //j是容积
            for (int j = m; j >=w[i]; j--) {
                //如果能选且还没有使用魔法
                f[j][0]=Math.max(f[j-w[i]][0]+v[i],f[j][0]);
                //已经使用过魔法了
                if (w[i]+k<=j){
                    f[j][1]=Math.max(Math.max(f[j][1],f[j-w[i]][1]+v[i]),f[j-(w[i]+k)][0]+v[i]* 2L);
                }
            }
        }
        out.println(Math.max(f[m][1],f[m][0]));
        out.flush();
    }
}

相关文章:

  • Vue Admin Template关闭eslint校验,lintOnSave:false设置无效解决办法
  • MMpose初体验--多人姿态检测关键点检测
  • 【重识云原生】第六章容器6.4.2.2节——Pod使用(上)
  • T1023: Hello,World!的大小(信息学一本通C++)
  • 前端工程师4.0
  • 分别将Map以Key或Vale进行排序
  • Selenium之入门
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • 7、乐趣国学—趣谈“圣贤”
  • 35分钟了解sql注入-盲注(三)
  • python求解四位数 青少年编程电子学会python编程等级考试三级真题解析2021年6月
  • SpringCloudAlibaba之gateway网关
  • 七牛云配置自定义域名
  • Spring/IoC、DI、Bean
  • 信息管理java毕业设计项目分享【含源码+论文】
  • #Java异常处理
  • android 一些 utils
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • canvas 五子棋游戏
  • CSS魔法堂:Absolute Positioning就这个样
  • exports和module.exports
  • javascript从右向左截取指定位数字符的3种方法
  • Laravel 实践之路: 数据库迁移与数据填充
  • Web标准制定过程
  • 关于extract.autodesk.io的一些说明
  • 将 Measurements 和 Units 应用到物理学
  • 前端面试之闭包
  • 使用API自动生成工具优化前端工作流
  • 鱼骨图 - 如何绘制?
  • 云大使推广中的常见热门问题
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • ​Spring Boot 分片上传文件
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • # 达梦数据库知识点
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #!/usr/bin/python与#!/usr/bin/env python的区别
  • (1)虚拟机的安装与使用,linux系统安装
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (五)关系数据库标准语言SQL
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (正则)提取页面里的img标签
  • (转)Linux下编译安装log4cxx
  • (轉貼) UML中文FAQ (OO) (UML)
  • . Flume面试题
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .net和jar包windows服务部署
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • @RequestParam详解
  • [HCTF 2018]WarmUp (代码审计)
  • [LeetCode] 93. Restore IP Addresses 复原IP地址