部分背包问题

问题

题目描述:

image

输入描述:

第一行两个整数N,T。
接下来N行,每行两个整数mi,vi。

输出描述:

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

样例输入:

4 50
10 60
20 100
30 120
15 45

样例输出:

240.00

思考

贪心问题,每次选取都选取性价比最高的金币(价值除以重量)。对输入的数据按照性价比从高到低进行排序。这里采用了结构体来表示金币堆,结构体有4个属性:1.重量2.价值3.性价比4.金币是否还有余量bool型数据。不用也行,但是用了或许会更加的方便。

typedef struct coin
{
    int m;          //质量
    int v;          //价值
    float mv;       // v/m的值
    bool is = true; //还有金币吗?
} coin;

还有一个值得注意的问题,一定要关注数据类型,把该转换的数据转换成double型,因为要做除法。

因为已经将金币堆按性价比从高到低排好了,所以直接循环遍历一遍就好了。

    while (T > 0)
    {
        for (i = 0; i < N; i++)
        {
            if (c[i].is) //金币还有吗  有
            {
                if (T > c[i].m) //背包足以装下全部这堆金币
                {
                    V += c[i].v;
                    T -= c[i].m;
                    c[i].is = false;
                }
                else //只能装下部分金币
                {
                    V += T * c[i].v / double(c[i].m);
                    T = 0;
                    break;
                }
            }
        }
    }

代码:

点击查看代码
#include <iostream>
#include <iomanip>
using namespace std;
typedef struct coin
{
    int m;          //质量
    int v;          //价值
    float mv;       // v/m的值
    bool is = true; //还有金币吗?
} coin;
int main()
{
    int N;
    float T; // N堆金币,背包容量为T
    cin >> N >> T;
    coin c[N];
    for (int i = 0; i < N; i++)
    {
        cin >> c[i].m >> c[i].v;
        c[i].mv = double(c[i].v) / c[i].m;
    }
    //直接插入排序,按照性值比进行排序,由高到低
    int i = 1;
    while (i < N)
    {
        int pre = i - 1;
        coin now = c[i];
        while (pre >= 0 && now.mv > c[pre].mv)
        {
            c[pre + 1] = c[pre];
            pre--;
        }
        c[pre + 1] = now;
        i++;
    }
    float V = 0;
    //贪心
    while (T > 0)
    {
        for (i = 0; i < N; i++)
        {
            if (c[i].is) //金币还有吗  有
            {
                if (T > c[i].m) //背包足以装下全部这堆金币
                {
                    V += c[i].v;
                    T -= c[i].m;
                    c[i].is = false;
                }
                else //只能装下部分金币
                {
                    V += T * c[i].v / double(c[i].m);
                    T = 0;
                    break;
                }
            }
        }
    }
    cout << fixed << setprecision(2) << V << endl;
    return 0;
}

posted @ 2022-03-20 20:06  请去看诡秘之主  阅读(55)  评论(0)    收藏  举报