现有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 。要求保留小数点后两位,第三位按照四舍五入处理。用c语言实现
时间: 2024-02-20 20:56:41 浏览: 53
给定n种物品和一个背包
5星 · 资源好评率100%
这是一个经典的背包问题,可以使用动态规划算法来解决。具体思路如下:
1. 定义状态:设dp[i][j]表示前i件物品放入容量为j的背包中所获得的最大价值。
2. 状态转移方程:对于第i件物品,有两种情况:放入背包和不放入背包。如果放入背包,则可以得到dp[i-1][j-w[i]]+p[i]的价值;如果不放入背包,则可以得到dp[i-1][j]的价值。因此,状态转移方程为:dp[i][j] = max(dp[i-1][j-w[i]]+p[i], dp[i-1][j])。
3. 初始化:当容量为0时,无论有多少件物品,背包中的价值都为0;当物品数量为0时,无论背包容量为多少,价值也都为0。
4. 求解:最终的结果为dp[n][M],即前n件物品放入容量为M的背包中所获得的最大价值。
5. 装包方法:由于动态规划只求出了最大价值,需要再进行一次遍历,确定每种物品放入背包的数量。具体做法是从dp[n][M]开始,逆推回去,如果dp[i][j]等于dp[i-1][j],说明第i件物品没有放入背包中;否则,第i件物品放入了背包中,其放入数量为x[i]=(M-w[i])/w[i]。
以下是C语言实现代码:
```c
#include <stdio.h>
#include <math.h>
int main() {
int M, n;
scanf("%d%d", &M, &n);
int w[n+1], p[n+1];
double x[n+1];
for (int i = 1; i <= n; i++) {
scanf("%d", &w[i]);
}
for (int i = 1; i <= n; i++) {
scanf("%d", &p[i]);
}
int dp[n+1][M+1]; // 定义状态数组
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= M; j++) {
if (i == 0 || j == 0) {
dp[i][j] = 0; // 初始化
} else if (j >= w[i]) {
dp[i][j] = fmax(dp[i-1][j], dp[i-1][j-w[i]]+p[i]); // 状态转移方程
} else {
dp[i][j] = dp[i-1][j];
}
}
}
int max_val = dp[n][M]; // 最大价值
printf("%d\n", max_val);
for (int i = n; i >= 1; i--) {
if (dp[i][M] > dp[i-1][M]) {
x[i] = (double)(M-w[i]) / w[i]; // 计算放入数量
M -= w[i] * x[i];
} else {
x[i] = 0;
}
}
for (int i = 1; i <= n; i++) {
printf("%.2lf ", x[i]);
}
printf("\n");
return 0;
}
```
示例输入:
```
10 5
2 3 4 5 9
3 4 5 8 10
```
示例输出:
```
29
0.00 0.00 1.00 0.00 1.00
```
阅读全文