【背包问题】列有一堆物品S=(a1,a2…an),每一个物品ai都有对应的重量wi和价值vi。现在有一个背包,容量为C。现在要选择物品装入背包,所选物品重量不能超过背包容量,并使得背包里物品价值最大。与0-1背包不同的是,可以对物品进行分割,即可以只选取物品ai的一部分装入背包。 将物品按照单位价值大小排序。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// 定义结构体
typedef struct {
double value; // 物品的价值
double weight; // 物品的重量
double ratio; // 物品的性价比
double in; // 物品装入背包的重量
int index; // 物品的编号
} Good;
// 比较函数,用于排序
int compare(const void *a, const void *b) {
Good *goodA = (Good *)a;
Good *goodB = (Good *)b;
return (int)(goodB->ratio - goodA->ratio); // 降序排序
}
// 求最大价值
double knapsack(Good *goods, int n, double v) {
// 先将货物按照性价比排序
qsort(goods, n, sizeof(Good), compare);
// 从性价比高的开始装入背包
double rem = v; // 背包的剩余容量
double sum = 0; // 背包的总价值
for (int i = 0; i < n; i++) {
if(rem > 0) {
if(rem > goods[i].weight) {
rem -= goods[i].weight;
goods[i].in = goods[i].weight;
sum += goods[i].value;
} else {
goods[i].in = goods[i].weight - rem;
sum += rem * goods[i].ratio;
rem = 0;
break;
}
}
}
return sum;
}
// 主函数
int main() {
int n; // 物品数量
printf("请输入物品数量:");
scanf("%d", &n);
Good *goods = (Good *)malloc(n * sizeof(Good));
if (goods == NULL) {
printf("内存分配失败\n");
return 1;
}
// 输入物品信息
for (int i = 0; i < n; i++) {
printf("请输入第%d个物品的价值:", i + 1);
scanf("%lf", &goods[i].value);
printf("请输入第%d个物品的重量:", i + 1);
scanf("%lf", &goods[i].weight);
goods[i].ratio = goods[i].value / goods[i].weight;
goods[i].index = i + 1;
}
// 背包容量
double v;
printf("请输入背包容量:");
scanf("%lf", &v);
// 计算最大价值
double max_value = knapsack(goods, n, v);
printf("最大价值为:%.2lf\n", max_value);
// 释放内存
free(goods);
return 0;
}
运行结果: