部分背包问题
问题
题目描述:

输入描述:
第一行两个整数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;
}

浙公网安备 33010602011771号