ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

贪心算法经典例题:背包问题(C++ 代码逐行讲解)

贪心算法经典例题:背包问题(C++ 代码逐行讲解) 1. 题目背景这段代码解决的是经典的部分背包问题Fractional Knapsack给定x件物品每件物品有质量m和价值v背包容量为y要求在不超过背包容量的前提下使装入背包的物品总价值最大。与 0-1 背包不同这里的物品可以分割比如大米、面粉、金砂所以我们可以按比例取走一部分这就让贪心策略成为可能。2. 核心思路贪心策略贪心的关键在于性价比——单位质量的价值v / m。我们总是优先选择「单位价值最高」的物品能全装就全装装不下就按剩余容量取一部分直到背包装满。这个策略之所以正确是因为物品可分割只要每次都拿当前性价比最高的最终一定能得到全局最优解。3. 代码逐行讲解3.1 结构体与全局数组structValue{floatm;// 物品质量floatv;// 物品价值};Value values[105];// 最多 105 件物品定义结构体Value保存每件物品的质量m和价值v并用全局数组values存储所有物品。3.2 排序比较函数boolcmp(Value a,Value b){returna.vb.v;// 按单位价值降序排列}这是sort的比较函数。注意在main中已经提前把v变成了「单位价值」v / m所以这里直接按v降序排序即可性价比高的物品排在前面。3.3 主函数输入与预处理intx,y;cinxy;// x 件物品背包容量 yfor(inti0;ix;i){cinvalues[i].m;// 输入质量cinvalues[i].v;// 输入价值}for(inti0;ix;i){values[i].v/values[i].m;// 计算单位价值 v/m}先读入物品数量和背包容量再读入每件物品的质量与价值。随后把每件物品的v原地更新为单位价值v / m为排序做准备。3.4 排序sort(values,valuesx,cmp);按单位价值从高到低排序性价比最高的物品排在最前面。3.5 贪心装入floatsum0;for(inti0;ix;i){if(values[i].my){// 当前物品能整件装下sumvalues[i].m*values[i].v;// 全装价值 质量 × 单位价值y-values[i].m;// 剩余容量减少}else{// 装不下整件只能装一部分sumy*values[i].v;// 用剩余容量 y 乘以单位价值break;// 背包已满结束}}printf(%.2f,sum);// 保留两位小数输出最大总价值这是核心循环若当前物品质量m不超过剩余容量y就整件装入累加价值m × v此时v是单位价值并扣减剩余容量若装不下整件就按剩余容量取一部分累加y × v然后break结束——因为背包已经满了后面的物品即使性价比再高也装不进去了。最后用printf(%.2f, sum)保留两位小数输出结果。4. 复杂度分析时间复杂度排序为O(x log x)贪心装入为O(x)整体O(x log x)。空间复杂度O(x)用于存储物品数组。5. 易错点提醒单位价值要提前算好排序前必须把v更新为v / m否则排序依据错误。浮点精度m、v用float计算v / m时注意类型避免整数除法丢失小数。break不能漏当装不下整件、只能取一部分时背包已满必须跳出循环否则会继续错误累加。输出格式题目要求保留两位小数用printf(%.2f, sum)或cout fixed setprecision(2)。6. 总结这段代码是贪心算法处理部分背包问题的经典实现先算性价比单位价值按性价比降序排序再依次装入装不下就取一部分。理解「物品可分割」这一前提是理解整个贪心策略正确性的关键。
返回列表