一、最优装载问题
给定一个最大装载重量为 M 的卡车和 N 种食品,有食盐、白糖、大米等。已知第 i 种食品最多有 Wi 公斤,其商品价值为 Vi 元/公斤,编程确定一个装货方案,使得装入卡车中所有物品总价值最大。
二、解题思路
因为每一个物品都可以分割成单位块,单位块的利益越大显然总收益越大,所以局部最优满足全局最优,可以使用贪心法解答。方法如下:
- 先将单位块收益从大到小进行排列;
- 初始化卡车的剩余载重和当前价值;
- 从前到后考虑所有物品:
a. 如果可以完全放入,当前价值加上物品总价值,剩余载重减去物品重量;
b. 如果只能部分放入,当前价值加上物品价值*剩余载重,使用剩余载重为0。
三、代码实现
#include <stdio.h>
#include <stdlib.h>
#define N 100
double GreedyBack(struct goods a[], int n, double c);
int cmp(const void *a, const void *b);
struct goods
{
double w, v;
};
int main()
{
int n;
double load, value; //货车总载重量和所载物品最大价值
struct goods a[N];
printf("请输入货车载重量:\n");
scanf("%lf", &load);
printf("请输入商品种类数:\n");
scanf("%d", &n);
printf("请输入%d种商品的质量和价格:\n", n);
for (int i = 0; i < n; i ++)
scanf("%lf%lf", &a[i].w, &a[i].v);
qsort(a, n, sizeof(a[0]), cmp); //按单位价格排序
value = GreedyBack(a, n, load);
printf("装入卡车的所有物品最大价值为:%.2f\n", value);
}
int cmp(const void *a, const void *b)
{
struct goods *c, *d;
c = (struct goods *)a;
d = (struct goods *)b;
return c->v < d->v ? 1: -1;
}
double GreedyBack(struct goods a[], int n, double c)
{
double sum = 0;
for (int i = 0; i < n; i ++)
if (a[i].w <= c) //如果第i个物品能全部装入
{
sum += a[i].v * a[i].w;
c -= a[i].w;
}
else
{
sum += c * a[i].v;
break;
}
return sum;
}
代码中排序的部分我也是比葫芦画瓢(声明cmp函数,其返回值为int型,参数为两个不可修改的void型指针),详细请看博客:qsort cmp的用法。