csp信奥赛C++高频考点专项训练之贪心算法 --【部分背包问题】:部分背包问题

csp信奥赛C++高频考点专项训练之贪心算法 --【部分背包问题】:部分背包问题

#### 题目描述

阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 N ( N ≤ 100 ) N(N \le 100) N(N≤100) 堆金币,第 i i i 堆金币的总重量和总价值分别是 m i , v i ( 1 ≤ m i , v i ≤ 100 ) m_i,v_i(1\le m_i,v_i \le 100) mi,vi(1≤mi,vi≤100)。阿里巴巴有一个承重量为 T ( T ≤ 1000 ) T(T \le 1000) T(T≤1000) 的背包,但并不一定有办法将全部的金币都装进去。他想装走尽可能多价值的金币。所有金币都可以随意分割,分割完的金币重量价值比(也就是单位价格)不变。请问阿里巴巴最多可以拿走多少价值的金币?

输入格式

第一行两个整数 N , T N,T N,T。

接下来 N N N 行,每行两个整数 m i , v i m_i,v_i mi,vi。

输出格式

一个实数表示答案,输出两位小数。

输入输出样例 1
输入 1
复制代码
4 50
10 60
20 100
25 100
15 45
输出 1
复制代码
240.00

思路分析

这是一个典型的部分背包问题 (也称为分数背包问题)。与 0/1 背包不同,金币可以任意分割,因此最优策略是优先选择单位价值(价值/重量)最高的金币堆,直到背包装满。

具体步骤

  1. 计算每堆金币的单位价值 avg = v / m
  2. 将所有金币堆按 avg 降序排序。
  3. 遍历排序后的金币堆:
    • 如果当前堆可以全部装入,则全部拿走,背包容量减少,总价值增加。
    • 否则,只装入剩余容量所能容纳的部分(按比例计算价值),然后结束。
  4. 输出总价值,保留两位小数。

时间复杂度:排序 O(N log N),遍历 O(N),满足 N ≤ 100 的约束。


代码实现

cpp 复制代码
#include<bits/stdc++.h> 
using namespace std;

struct node {  
    double m, v, avg;   // 重量、总价值、单位价值
} a[110];  

bool cmp(node x, node y) {  
    return x.avg > y.avg; // 按单位价值降序排序
}

int main() {
    int n, t; // n:堆数, t:背包容量
    cin >> n >> t;
    for (int i = 1; i <= n; i++) {
        cin >> a[i].m >> a[i].v;
        a[i].avg = a[i].v / a[i].m; // 计算单位价值
    }
    sort(a + 1, a + n + 1, cmp);  // 贪心排序

    double ans = 0; // 记录最大价值
    for (int i = 1; i <= n && t > 0; i++) {
        if (t >= a[i].m) { // 能全部装下
            ans += a[i].v;
            t -= a[i].m;
        } else { // 只能装部分
            ans += t * a[i].avg; // 按比例计算价值
            t = 0;// 背包已满
        }
    }
    printf("%.2lf\n", ans); // 输出两位小数
    return 0;
}

功能分析

  • 输入处理 :读取金币堆数 n 和背包容量 t,再依次读取每堆的重量 m 和价值 v
  • 单位价值计算avg = v / m,用于贪心决策。
  • 排序:按单位价值从高到低排列,确保优先取"性价比"最高的金币。
  • 贪心装载
    • 若当前堆能完全装入,则全部拿走。
    • 否则只取剩余容量对应的部分(重量 × 单位价值),背包随即装满。
  • 输出 :使用 printf 格式化输出两位小数的最大价值。

各种学习资料,助力大家一站式学习和提升!!!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"##########  一站式掌握信奥赛知识!  ##########";
	cout<<"#############  冲刺信奥赛拿奖!  #############";
	cout<<"######  课程购买后永久学习,不受限制!   ######";
	return 0;
}

【秘籍汇总】(完整csp信奥赛C++学习资料):

1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

https://edu.csdn.net/lecturer/7901 点击跳转

2、CSP信奥赛C++竞赛拿奖视频课:

https://edu.csdn.net/course/detail/40437 点击跳转

https://edu.csdn.net/course/detail/41081 点击跳转

3、csp信奥赛高频考点知识详解及案例实践:

CSP信奥赛C++动态规划:
https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

CSP信奥赛C++标准模板库STL:
https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

信奥赛C++提高组csp-s知识详解及案例实践:
https://blog.csdn.net/weixin_66461496/category_13113932.html 点击跳转

4、csp信奥赛冲刺一等奖有效刷题题解:

CSP信奥赛C++初赛及复赛高频考点真题解析(持续更新): https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13125089.html 点击跳转

5、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

GESP(C++ 七级+八级)真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13117178.html 点击跳转

· 文末祝福 ·

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"跟着王老师一起学习信奥赛C++";
	cout<<"    成就更好的自己!       ";
	cout<<"  csp信奥赛一等奖属于你!   ";
	return 0;
}
相关推荐
handler012 小时前
【Linux 笔记】GDB 调试速查手册
linux·运维·c语言·c++·笔记
九思十安2 小时前
HNU2026-算法设计与分析-笔记 3 摊还分析
笔记·算法
无忧.芙桃2 小时前
现代C++讲解之enum class,static_assert,tuple的使用
开发语言·c++
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 142. 环形链表 II | C++ 哈希表直觉解法
c++·leetcode·链表
嘻嘻哈哈樱桃2 小时前
牛客经典101题题解集--哈希
java·数据结构·python·算法·leetcode·职场和发展·哈希算法
fish_xk2 小时前
c++中的继承
开发语言·c++
自我意识的多元宇宙2 小时前
【数据结构】 红黑树
数据结构·算法
wayz112 小时前
Day 15 编程实战:KMeans聚类与股票风格分类
算法·机器学习·分类·kmeans·聚类
不知名的老吴2 小时前
数据结构与算法之排序算法
算法·排序算法