洛谷题单【算法1-5】贪心——P2240 【深基12.例1】部分背包问题

163 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情

P2240 【深基12.例1】部分背包问题

题目描述

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

输入格式

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

接下来 NN 行,每行两个整数 mi,vim_i,v_i

输出格式

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

样例 #1

样例输入 #1

4 50
10 60
20 100
30 120
15 45

样例输出 #1

240.00

思路

题目说是背包问题,其实和背包问题关系不大

做法就是贪心

对于每一堆金币创建一个结构体,内部存放着金币的个数和重量

对于金币重量比对结构体数组进行排序

然后从前往后尽可能多的拿取金币即可

代码

// P2240 【深基12.例1】部分背包问题
// 贪心+结构体排序
#include <bits/stdc++.h>
using namespace std;
struct gold
{
    int w;
    float v;
}gg[110];

bool cmp(gold a, gold b){
    //回调函数
    return (a.v/a.w) > (b.v/b.w);
}

int main(int argc, char const *argv[])
{
    float ret = 0;
    float nowt,t;
    int n;
    cin >> n >> t;
    nowt = t;
    //读取数据
    for(int i=0; i<n; i++){
        cin >> gg[i].w >> gg[i].v;
    }
    sort(gg, gg+n, cmp);
    for(int i=0; i<n; i++){
        if(gg[i].w <= nowt){
            ret += gg[i].v;
            nowt -= gg[i].w;
        } else if(gg[i].w > nowt){
            ret += nowt*gg[i].v/gg[i].w;
            break;
        }
    }

    printf("%.2f",ret);
    return 0;
}