题目描述
给定一个最大容量为m的背包和n种物品,有食盐、白糖、大米等。已知第i种食品最多有wi公斤,其价值为vi元/公斤,请确定一个装货方案,使得装入背包中的所有食品的总价值最大。
题目分析
考虑到物品可以分块进行装载,即每一个物品按重量可分割,所以采用单位价值大的先装满的原则进行贪心,代码如下:
代码示例
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
/**
* @author xyr
* @time 2020/12/20
* @func 贪心算法解决部分背包问题
*/
class stuff {
private:
float w, v;
string name;
public:
string Getname(){ return name; }
float Getvalue() { return v; }
void Setname(string name1) { name= name1; }
void Setweight(float w1){ w=w1; }
void Setvalue(float v1){ v=v1; }
stuff() { w = 0; v = 0; }
stuff(float v1, float w1) : v(v1), w(w1) {}
friend void Knapsack(stuff food[], float* x, int n, float c);
};
bool cmp(stuff a, stuff b) {
return a.Getvalue() > b.Getvalue();
}
void Knapsack(stuff food[], float* x, int n, float c) {
//先将传过来的物品按照单位质量的价值从大到小排序:
sort(food, food+n, cmp);
for (int i = 0; i < n; i++) {
if (food[i].w < c) {
x[i] = food[i].w;
c -= food[i].w;
}
else {
x[i] = c;
break;
}
}
}
int main() {
int n; //物品总数
float m; //背包容量
cout << "请输入物品总数: " << endl;
cin >> n;
cout << "请输入背包最大容量: 单位:公斤" << endl;
cin >> m;
float* w= new float[n], * v= new float[n], * x= new float[n];
string *name=new string[n];
cout << "请输入物品名:" << n << "件" << endl;
for (int i = 0; i < n; i++) {
cin >> name[i];
}
cout << "请输入物品重量:" << n << "件 单位:公斤" << endl;
for (int i = 0; i < n; i++) {
cin >> w[i];
}
cout << "请输入物品价值:" << n << "件 单位:元/公斤" << endl;
for (int i = 0; i < n; i++) {
cin >> v[i];
}
for (int i = 0; i < n; i++) {
x[i]=0;
}
stuff *food= new stuff[n];
for (int j = 0; j < n; j++) {
food[j].Setname(name[j]);
food[j].Setvalue(v[j]);
food[j].Setweight(w[j]);
}
Knapsack(food, x, n, m);
float sum = 0;
for (int i = 0; i < n; i++) {
cout << food[i].Getname()<< "装入" << x[i] << "公斤" << endl;
sum += food[i].Getvalue() * x[i];
}
cout << "最大价值为:" << sum << "元" << endl;
}
运行结果示例
food name:rice salt oil ,weight:10 40 20 kg, value: 8 1 40 RMB/kg ,max weight:50kg