用c语言写下面代码并给出详细注释 现有n种物品和一个可承载M 重量的背包,n种物品的重量分别为(w 1 , w 2 , …, w n ),n种物品放入背包所获得的效益分别是(p 1 , p 2 , …, p n ) (p i >0),p i 和w i 均是正整数,若将物品i的一部分x i (0<=x i <=1)放入背包,则所获得的效益是p i x i ,问采用怎样的装包方法会使装入背包物品的总效益为最大? 输入格式: 第1行是M和n,表示背包容量为M且有n件物品; 第2行是这n件物品的重量w i ; 第3行是各物品的价值p i 。 输出格式: 第1行是所选物品的最大价值之和; 第2行是各物品装入背包的量x i 。要求保留小数点后两位,第三位按照四舍五入处理。
时间: 2024-02-19 14:03:30 浏览: 57
```c
#include <stdio.h>
#include <stdlib.h>
#define MAX_N 1000
int n, m;
int w[MAX_N + 5], p[MAX_N + 5];
double f[MAX_N + 5][MAX_N + 5];
// 比较两个实数的大小
double max(double a, double b) {
return a > b ? a : b;
}
int main() {
// 读入数据
scanf("%d%d", &m, &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &w[i]);
}
for (int i = 1; i <= n; i++) {
scanf("%d", &p[i]);
}
// 动态规划求解最大价值
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
f[i][j] = f[i - 1][j]; // 不选第 i 个物品
if (j >= w[i]) { // 能够选第 i 个物品
f[i][j] = max(f[i][j], f[i - 1][j - w[i]] + (double)p[i] * w[i] / (double)w[i]); // 选择第 i 个物品
}
}
}
// 输出最大价值
printf("%.2lf\n", f[n][m]);
// 求解每个物品的装入量
double* x = (double*)malloc(sizeof(double) * (n + 1));
for (int i = n; i >= 1; i--) {
if (f[i][m] == f[i - 1][m]) { // 第 i 个物品未选
x[i] = 0;
} else { // 第 i 个物品被选
x[i] = (double)(m - w[i]) / (double)w[i]; // 计算 x[i]
m -= w[i] * x[i]; // 更新背包剩余容量
}
}
// 输出每个物品的装入量
for (int i = 1; i <= n; i++) {
printf("%.2lf ", x[i]);
}
printf("\n");
// 释放内存
free(x);
return 0;
}
```
注:本题的特殊之处在于每个物品只能选取一部分,因此在计算最大价值时需要将物品的效益按照单位重量价值(即 $p_i/w_i$)来计算。在求解每个物品的装入量时,为了保证最大化效益,我们采用贪心思想,优先选取单位重量价值最大的物品。
阅读全文