P14920 [GESP202512 六级] 道具商店

2025年12月GESP真题及题解(C++六级): 道具商店 阅读详情

记录132

#include<bits/stdc++.h> // 引入C++万能头文件,包含所有常用的标准库
using namespace std; // 使用标准命名空间std
#define ll long long // 定义长整型别名ll,因为金币数量最大为1e9,累加容易溢出int
const int MAX_SUM=250005; // 定义常量,表示所有道具攻击力总和的最大值(500*500)
const ll INF=1e18; // 定义一个极大的数作为无穷大,表示某种攻击力无法达到

int n; // 定义变量n,表示道具的总数量
ll k; // 定义变量k,表示玩家拥有的金币总数(预算上限)
int a[505],c[505]; // 定义数组,a[i]表示第i件道具的攻击力,c[i]表示购买所需的金币
ll dp[MAX_SUM]; // 定义dp数组,dp[j]表示获得j点攻击力所需要的最少金币数
int total_a=0; // 定义变量total_a,用来累加所有道具的攻击力总和

int main(){ // 主函数入口
    ios::sync_with_stdio(false); // 关闭标准流同步,提升输入输出效率
    cin.tie(0); // 解除cin与cout的绑定,加快读取速度
    
    cin>>n>>k; // 读入道具数量和金币总数
    for(int i=1;i<=n;i++){ // 循环读入每件道具的信息
        cin>>a[i]>>c[i]; // 读入第i件道具的攻击力和花费
        total_a+=a[i]; // 累加攻击力总和,作为dp数组的遍历上界
    }
    
    // 初始化dp数组:除了0点攻击力花费0金币外,其余状态都初始化为无穷大(表示不可达)
    for(int i=0;i<=total_a;i++){
        dp[i]=INF;
    }
    dp[0]=0; // 获得0点攻击力不需要花费任何金币
    
    // 01背包核心循环:遍历每一件道具
    for(int i=1;i<=n;i++){
        // 逆序遍历攻击力(从大到小),这是01背包一维数组优化的经典操作,防止同一件道具被重复选取
        for(int j=total_a;j>=a[i];j--){
            // 状态转移方程:取“不买当前道具”和“买当前道具”两者中花费金币较少的方案
            dp[j]=min(dp[j],dp[j-a[i]]+c[i]);
        }
    }
    
    int ans=0; // 定义变量ans,用来记录最终的最大攻击力
    // 遍历所有可能的攻击力,找到花费在预算k以内的最大攻击力
    for(int j=0;j<=total_a;j++){
        if(dp[j]<=k){ // 如果获得j点攻击力的最小花费不超过拥有的金币数
            ans=max(ans,j); // 更新最大攻击力
        }
    }
    
    cout<<ans<<"\n"; // 输出最多可以提升的攻击力点数
    return 0; // 程序正常结束
}

题目传送门https://www.luogu.com.cn/problem/P14920


前言

我是一名专注信奥赛(CSP-J/S、NOIP)的教练。

  • 如果你觉得这篇题解对你有帮助,欢迎点击关注我的优快云账号,我会持续更新高质量算法解析。
  • 我深知算法思维的构建远比单纯通过题目更重要,本系列题解不局限于AC代码的堆砌,而是致力于拆解题目背后的逻辑链条与核心知识点
  • 备赛路上若遇瓶颈,欢迎随时评论或私信,我将甄选典型疑难问题,通过视频讲解或撰写专项文章的形式,为你提供深度答疑。

 核心解题思路

这道题是一道经典的01背包问题的变种。

  1. 常规思路的瓶颈:
    在标准的背包问题中,我们通常定义 dp[j] 为“花费 j 枚金币能获得的最大攻击力”。但是,本题中金币数量 k 和道具花费 c_i 最大可达 10^9,如果以金币作为背包容量,数组根本开不下,时间复杂度也会严重超标。

  2. 逆向思维(交换价值与代价):
    观察数据范围,道具数量 n 最大只有 500,每件道具的攻击力 a_i 最大只有 500。这意味着,所有道具的攻击力总和最大仅为 500 × 500 = 250000。
    因此,我们可以将“代价”和“价值”互换:定义 dp[j] 为“获得 j 点攻击力所需要的最少金币数”。这样,背包的容量就变成了攻击力总和(约 2.5 × 10^5),完全在可接受的范围内。

  3. 状态转移与答案提取:
    状态转移方程为:dp[j] = min(dp[j], dp[j - a_i] + c_i)。
    在计算出所有攻击力对应的最小花费后,我们只需要从大到小(或遍历所有)寻找满足 dp[j] ≤ k(花费在预算内)的最大的 j,即为最终答案。


 代码分块详细解释

1. 头文件、常量与全局变量定义

#include<bits/stdc++.h> 
using namespace std; 
#define ll long long // 定义长整型别名 ll,因为金币数量最大为 1e9,累加容易溢出 int
const int MAX_SUM=250005; // 定义常量,表示所有道具攻击力总和的最大值 (500*500)
const ll INF=1e18; // 定义一个极大的数作为无穷大,表示某种攻击力无法达到

int n; // 定义变量 n,表示道具的总数量
ll k; // 定义变量 k,表示玩家拥有的金币总数(预算上限)
int a[505], c[505]; // 定义数组,a[i] 表示第 i 件道具的攻击力,c[i] 表示购买所需的金币
ll dp[MAX_SUM]; // 定义 dp 数组,dp[j] 表示获得 j 点攻击力所需要的最少金币数
int total_a=0; // 定义变量 total_a,用来累加所有道具的攻击力总和
  • 详细分析:这部分奠定了算法的基础。由于金币花费可能达到 109,累加后极易超出 int 范围,因此金币相关变量和 dp 数组必须使用 long long。INF 被设置为 1018,用于初始化 dp 数组,代表“当前攻击力暂时无法达到”的状态。MAX_SUM 的设定非常巧妙,它利用了题目中 a_i 和 n 较小的约束,将背包容量压缩到了 2.5 × 105 级别。

2. 输入处理与数据准备

int main(){ 
    ios::sync_with_stdio(false); // 关闭标准流同步,提升输入输出效率
    cin.tie(0); // 解除 cin 与 cout 的绑定,加快读取速度
    
    cin>>n>>k; // 读入道具数量和金币总数
    for(int i=1;i<=n;i++){ // 循环读入每件道具的信息
        cin>>a[i]>>c[i]; // 读入第 i 件道具的攻击力和花费
        total_a+=a[i]; // 累加攻击力总和,作为 dp 数组的遍历上界
    }
  • 详细分析:在读取数据的同时,程序计算了所有道具的攻击力总和 total_a。这个变量至关重要,它决定了后续 dp 数组需要遍历的确切范围,避免了无意义的循环,进一步提升了程序的运行效率。

3. DP 数组初始化

    // 初始化 dp 数组:除了 0 点攻击力花费 0 金币外,其余状态都初始化为无穷大(表示不可达)
    for(int i=0;i<=total_a;i++){
        dp[i]=INF;
    }
    dp[0]=0; // 获得 0 点攻击力不需要花费任何金币
  • 详细分析:这是一个标准的“求最小值”型 DP 的初始化操作。将状态初始化为无穷大,是为了在后续的状态转移方程 min() 中,能够正确地筛选出真正的最小花费。dp[0] = 0 则是动态规划的基准状态。

4. 01 背包核心循环

    // 01背包核心循环:遍历每一件道具
    for(int i=1;i<=n;i++){
        // 逆序遍历攻击力(从大到小),这是 01背包一维数组优化的经典操作,防止同一件道具被重复选取
        for(int j=total_a;j>=a[i];j--){
            // 状态转移方程:取“不买当前道具”和“买当前道具”两者中花费金币较少的方案
            dp[j]=min(dp[j],dp[j-a[i]]+c[i]);
        }
    }
  • 详细分析:这是算法的灵魂。
    • 逆序遍历的必要性:因为每件道具只能购买一次(01背包),在更新 dp[j] 时,我们需要依赖上一轮(未购买当前道具时)的 dp[j - a_i] 的状态。如果正序遍历,dp[j - a_i] 会在当前轮次被提前更新,导致同一件道具被多次购买(这就变成了完全背包)。逆序遍历完美规避了这个问题。
    • 状态转移:dp[j - a_i] + c_i 表示为了凑出 j 点攻击力,我们选择购买第 i 件道具,那么就需要在凑出 j - a_i 点攻击力的最小花费基础上,再加上当前道具的花费 c_i。

5. 提取答案与输出

    int ans=0; // 定义变量 ans,用来记录最终的最大攻击力
    // 遍历所有可能的攻击力,找到花费在预算 k 以内的最大攻击力
    for(int j=0;j<=total_a;j++){
        if(dp[j]<=k){ // 如果获得 j 点攻击力的最小花费不超过拥有的金币数
            ans=max(ans,j); // 更新最大攻击力
        }
    }
    
    cout<<ans<<"\n"; // 输出最多可以提升的攻击力点数
    return 0; // 程序正常结束
}
  • 详细分析:在完成了所有的状态转移后,dp 数组中存储了获得任意攻击力所需的最小金币数。最后一步只需要线性扫描一遍 dp 数组,找出所有满足“最小花费 ≤ 玩家总金币 k”的攻击力 j 中的最大值,即为题目所求。

核心逻辑总结表

代码模块核心变量/操作精炼作用解决的痛点
逆向建模dp[j] = 获得 j 攻击力的最小金币交换背包的“代价”与“价值”解决了金币数高达 109,无法作为数组下标的致命问题
数据范围利用total_a 累加攻击力确定 DP 数组的实际遍历上界利用 n 和 a_i 较小的特点,将复杂度限制在 O(n × Σa_i)
01背包防重for(j=total_a; j>=a[i]; j--)逆序遍历背包容量保证每件道具只被计算一次,符合“每件道具只能购买一次”的题意
极值初始化dp[i]=INF, dp[0]=0设定求最小值的基准状态确保状态转移方程 min() 能够正确计算出真实的最小花费
答案提取if(dp[j]<=k) ans=max(ans,j)在预算约束下寻找最优解将计算出的“最小花费表”转化为题目要求的“最大攻击力”
题解:洛谷 P14920 [GESP202512 六级] 道具商店 等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。,表示道具所提升的攻击力点数,以及购买所需的金币数量。枚金币才能购买,每件道具只能购买一次。输出一行,一个整数,表示最多可以提升的攻击力点数。枚金币,请问你最多可以提升多少点攻击力?,表示道具数量以及你所拥有的金币数量。本文分享的必刷题目是从。 阅读详情

相关推荐

合宙Air780EP速连OneNET:AT+MQTT应用指南

本文详细讲解了合宙Air780EP使用AT指令通过MQTT接入OneNET的过程。

2401_82812461的博客 1390

CCF-GESP计算机学会等级考试2025年12月六级C++T2 道具商店

摘要: 题目P14920是一道变形01背包问题,玩家需在金币有限的情况下购买道具以最大化攻击力提升。由于金币上限高达$10^9$,常规01背包解法不可行。解题核心是维度转换:将状态定义为dp[j]表示获得j攻击力的最小金币消耗(攻击力总和上限仅250000)。通过逆序01背包处理,最后遍历所有攻击力值,找到满足dp[j]≤k的最大j即为答案。该解法巧妙利用数据范围特点(攻击力数值小),将问题转化为可处理的常规背包模型。

长春高老师编程 1367

【吐血整理-历时两个月,长达万字】FDTD Solutions学习笔记

原教学视频来自于Ansys-Lumerical官方的FDTD100,所看视频来自B站大佬UP主 【Nestor_呐等】 的幸苦翻译,本文内容粘贴自我个人在学习FDTD100时,通过字幕和一些个人理解总结的一份word。整理不易,强烈建议收藏!...

weixin_45719141的博客 10万+

[GESP202512 六级 T2] 道具商店

(T1以后会发布)

Zac04的博客 1089

【C语言】程序员筑基功法——《函数栈帧的创建与销毁》

汇编角度带你走进函数栈帧

StackFrame 3663

控制科学与工程(自动化)保研经验【1】——预备篇

个人情况 学校:中末流211 专业:自动化(学科评估B-) 年份:2019 排名:4/128 绩点:4.16/5 竞赛:三个国二(包括数模国赛美赛)、两个省一(机器人、电子设计竞赛) 【本科期间竞赛做的比较多,是我的一大亮点,可以在筛简历这关适当弥补专业排名的不足】 科研:一个校级的大创项目(水) 夏令营报名:中科大科学岛、中科大本部、自动化所、沈自所、北航(仪器17系)、山大、浙江大学、南开、同...

Control Everything 1万+

《P14920 [GESP202512 六级] 道具商店》

该题目是一个典型的动态规划问题,属于0-1背包问题的变种。给定n件道具,每件道具提供ai攻击力但需要ci金币购买,要求在不超过k金币的前提下最大化攻击力。由于k的范围可能很大(1e9),传统背包解法不适用。高效解法是基于攻击力维度进行DP,记录达到特定攻击力所需的最小金币数,最后在不超过k的情况下寻找最大攻击力。时间复杂度为O(n*A),其中A是总攻击力上限(n≤500,ai≤500,总攻击力≤2.5e5)。输入样例1输出132,样例2输出110,验证了算法的正确性。关键点在于转换DP维度以处理大额k值。

Jasmine_llq的博客 164

使用亚组分析进行子组分析并可视化森林图 - R语言

通过亚组分析和森林图的结合,我们可以更好地理解不同子组之间的差异和效果大小。当然,在实际应用中,还需要考虑多种因素,如样本量、异质性等,以得到更准确的结果和结论。每个森林图中的水平线代表了每个子组的效应估计,线的长度表示了该效应估计的置信区间。假设我们有一个包含研究对象的数据框(data frame),其中包括了治疗组和对照组的结果数据,以及一些可能的影响因素作为调整变量。在本例中,我们将比较两种不同的治疗方法(A和B)对结果变量的影响,并调整了一个额外的变量。是结果变量和对照组变量的列名。

2301_79326857的博客 1237

【题解-洛谷】P14920 [GESP202512 六级] 道具商店

一开始我想这还普及啊,不是板子题嘛?结果一看k的范围,达到了1e9,在这等着呢!再看看攻击力的范围,只有2.5e5,那就把体积和价值对调一下吧。然后从大到小扫一遍f数组,只要f[j]<=k就输出当前攻击力。把攻击力作为体积,f[j]表示攻击力不超过j的最小金币数量。,表示道具所提升的攻击力点数,以及购买所需的金币数量。枚金币才能购买,每件道具只能购买一次。输出一行,一个整数,表示最多可以提升的攻击力点数。枚金币,请问你最多可以提升多少点攻击力?,表示道具数量以及你所拥有的金币数量。对于所有测试点,保证。

写代码的犄角旮瘩 156

CARLA仿真:自定义地图与AI车辆行为编程

CARLA仿真:自定义地图与AI车辆行为编程 ,人工智能,计算机视觉,大模型,AI,本文围绕CARLA仿真平台,介绍了其基础功能与安装方法,详解地图系统,包括预设地图的加载切换及自定义地图的创建、导入与优化。还阐述了AI车辆的创建、属性设置、销毁,以及行为控制,如交通规则遵守、路径规划、复杂行为编程和行为树应用。同时涉及传感器与车辆感知、交通场景构建、自定义地图与AI行为结合应用、高级应用,以及常见问题解决方案和学习资源,为CARLA仿真应用提供全面指导。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 11万+

[VCS]VCS checkpoint简介以及其在SoC验证加速中的作用

VCS checkpoint是Synopsys VCS提供的快照/恢复机制,可显著加速SoC验证。其核心是在仿真关键节点(如完成初始化后)保存系统状态,后续测试可直接从该点恢复,避免重复执行冗长的初始化阶段(如boot、DDR训练等)。该技术特别适用于多测试用例共享同一初始状态的场景,通过分离初始化与功能验证流程,可提升回归效率3-5倍。需注意处理DPI-C状态同步、版本管理及存储优化等问题,结合UVM和自动化脚本可实现更高效的验证流程。典型应用可节省数百万cycle的重复仿真时间。

元直的博客 779

记——那次难忘的GESP六级考试(202603)+编程题题解

本文记录了作者参加GESP六级考试的全过程,重点描述了备考和考试当天的经历。作者详细列出了自己完成的13道编程题目及解题思路,包括DP、贪心、树状数组等算法题,同时也提到未完成的8道题目。考试当天经历了忘带鼠标的意外,利用触控板继续练习。文章还提到选择题涉及动态规划、树遍历等基础知识,整体展现了作者从紧张备考到从容应考的心路历程,以及面对突发状况的应对能力。

2401_84010520的博客 641

STM32开发 -- GPIO详解

之前有简单讲过GPIO工作模式和寄存器,还是有点没搞明白。这次需要全方位的看一下了。 一、数据手册 1、STM32F105RC引脚说明 可知:STM32F105RC 一共有4组IO口 一共16X3+3=51个IO GPIOA0~A15 GPIOB0~B15 GPIOC0~C15 GPIOD0~D2 2、程序定义 GPIO端口号 STM32F1...

不积跬步,无以至千里 5万+

GESP认证C++编程真题解析 | 202512 六级

下面的函数能正确判断一棵树是不是二叉排序树(左边的数字要比当前数字小,右边的数字要比当前数字大)。虚函数的核心作用是实现运行时多态(动态绑定),即根据实际对象类型调用对应函数,A正确。在二叉排序树(BST)中,若某结点的左子树为空,则该结点一定是整棵树中的最小值结点。面向对象编程中,封装是指将数据和操作数据的方法绑定在一起,并对外隐藏实现细节。递推和递归都可以实现动态规划,在实现良好的情况下,两种方式的时间复杂度相当。递归处理左子树,递归处理右子树,最后输出根结点的信息,这种为后序遍历。

团爸讲算法 598

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

视频隐私脱敏工程化:CSRT/KCF追踪算法在本地推理中的实现与边界

在短视频内容合规审查中,动态遮挡(Dynamic Masking)是高频且高耗时的环节。传统手动关键帧打码不仅效率低下,且在目标快速移动或遮挡时极易出现遮罩漂移。本文从计算机视觉工程角度,解析基于CSRT与KCF算法的目标追踪方案在视频隐私处理中的技术路径、性能权衡及落地实践。

Mysssone的博客 304

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

把 KV Cache 压到 FP4:BitDecoding-FP4 的算法-系统协同设计复盘

长上下文推理卡在KV Cache的显存与带宽上,而现有FP4方案要么精度崩、要么速度废。这篇文章复盘BitDecoding-FP4如何用三个算法补丁加一个系统重构,在B300上把服务吞吐提升2.4–3.0倍,精度几乎不掉。

helloagent的博客 310

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【算法拾光】链表 哈希表|K个一组翻转链表 + 两数之和

K个一组翻转链表需分段反转,借助哑节点与前驱指针维护连接,避免断链;两数之和利用哈希表实现O(1)查找,空间换时间,高效定位目标组合。前者考察链表指针操作,后者聚焦映射关系构建,均为面试高频题。

wuqingyigexiaoba的博客 329

排序算法深度笔记(下):非比较类排序的线性突破与工程边界

排序算法时间复杂度额外空间复杂度稳定性是否基于比较选择排序O(N^2)(O(1))不稳定是冒泡排序O(N^2)(O(1))稳定是插入排序O(N^2)(O(1))稳定是归并排序O(N\log N)(O(N))稳定是快速排序O(N\log N)O(log N)不稳定是堆排序O(N\log N)O(1)不稳定是计数排序(O(N + M))O(M))稳定否基数排序O(N)稳定否桶排序平均O(N) / 最坏O(N^2)

2401_87069538的博客 601

优选算法:分治-归并排序

交易逆序对的总数

Wangshijie1015的博客 146

算法日常・每日刷题--<动态规划>42

本题为“不相交的线”,与最长公共子序列问题相似。使用动态规划求解:定义 dp[i][j] 表示 nums1[0:i] 与 nums2[0:j] 的最大不相交连线数。若元素相等,则继承左上值加1;否则取上方或左方最大值。最终返回 dp[m][n],即两数组的最大不相交连线数。时间复杂度 O(mn),空间复杂度 O(mn)。

2503_92261635的博客 24

408 算法 06|堆与 Top-K:最小的 10 个数,到底该用数组还是堆

2022(42) 找 100 万个数里最小的 10 个,官方给了"10 元素有序数组"和"大根堆"两种答案。我把两种都实现并数了比较次数:k=10 时两者几乎打平,k=10000 时堆少 111 倍。另附 2021(42) 计数排序的比较次数与稳定性实测。

m0_56226131的博客 435

408 算法 04|主元素与三元组最小距离:两种“扫描时做决定“的思路

2013(41) 的主元素用摩尔投票一遍选出候选,但真正的考点是"选完必须验票";2020(41) 的三元组最小距离,三指针每次只挪最小的那个,靠的是 D=2×(max−min) 这个恒等式。两套完整 C 代码加真实输出,附官方评分档位表。

m0_56226131的博客 417

牛客周赛165C题(前后缀性质,递推,排序,枚举)

题目大意:给定长度为 `n` 的数组,选择 `k ∈ [1,n]`,将前 `k` 个元素整体翻转,后面的元素不变。要求操作后的整个数组非递减,统计满足条件的 `k` 的数量。题目链接:https://ac.nowcoder.com/acm/contest/141721/C。时间复杂度:O(nlogn)

2501_94316951的博客 173

【MPC 算法】Python 实战:模型预测控制(MPC)算法原理与代码实现

本文介绍模型预测控制(MPC)原理与Python实现。MPC通过滚动优化预测未来状态,结合系统模型、目标函数与约束条件,动态生成最优控制序列。以一阶温度系统为例,使用CVXPY构建凸优化问题,实现加热功率的智能调控。代码包含模型预测、目标函数设计(含温度跟踪与控制平滑惩罚)、输入约束及滚动更新机制。仿真结果表明,MPC能快速稳定温度至目标值60℃,且控制动作平滑合理,体现其在复杂系统中的优越性。

赖德发的博客 41

算法61,判定是否为字符重排

两字符串能互为重排 ⇔。

sheshibenniaodan的博客 221

算法日常・每日刷题--<动态规划>32

给定严格递增的正整数数组,求最长斐波那契子序列长度。使用二维DP,dp[i][j]表示以arr[i]、arr[j]为最后两项的序列长度,初始化均为2。通过哈希表快速查找前一项target = arr[j] - arr[i],若存在且下标小于i,则状态转移:dp[i][j] = dp[k][i] + 1。遍历更新全局最大长度,最终若结果小于3则返回0。时间复杂度O(n²),空间复杂度O(n²)。

2503_92261635的博客 180
上一篇: P14076 [GESP202509 六级] 货物运输
下一篇: P15800 [GESP202603 六级] 选数
谢天谢地AC了 | 信奥教练
博客等级 码龄1年 53粉丝 177原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值