0/1背包问题。给定一载重量为W的背包及n个重量为wi、价值为vi的物体,1≤i≤n,要求而且重量和恰好为W具有最大的价值
输入格式:
第一行输入背包载重量W及背包个数n,再依次输入n行,每行为背包重量wi和价值vi。
输出格式:
第一行输出输出装入背包内的物体编号(末尾有空格),第二行输出背包内的物体总重量和总价值。
输入样例1:
5 10
2 6
2 3
6 5
5 4
4 6
输出样例1:
1 2 3
10 14
代码解析:
#include <stdio.h> // 引入标准输入输出库
#include <string.h> // 引入字符串处理库
#include <iostream> // 引入C++标准输入输出库
#define MAXN 20 // 定义最大物品数为20
using namespace std; // 使用标准命名空间
int n; // 定义物品数变量
int W; // 定义背包限制重量变量
int w[MAXN] = {0}; // 定义存放物品重量的数组,下标从1开始
int v[MAXN] = {0}; // 定义存放物品价值的数组,下标从1开始
int x[MAXN]; // 定义存放最终解的数组
int maxv; // 定义存放最优解的总价值变量
// 定义求解0/1背包问题的函数
void dfs(int i, int tw, int tv, int rw, int op[]) {
int j;
if (i > n) { // 如果已经遍历完所有物品
if (tw == W && tv > maxv) { // 如果当前解满足条件且总价值大于已知最优解
maxv = tv; // 更新最优解的总价值
for (j = 1; j <= n; j++) { // 复制最优解到x数组
x[j] = op[j];
}
}
} else { // 如果还有未遍历的物品
if (tw + w[i] <= W) { // 如果当前物品可以放入背包
op[i] = 1; // 选取第i个物品
dfs(i + 1, tw + w[i], tv + v[i], rw - w[i], op); // 递归调用,尝试放入下一个物品
}
op[i] = 0; // 不选取第i个物品,回溯
if (tw + rw > W) { // 如果右子树剪枝条件成立
dfs(i + 1, tw, tv, rw - w[i], op); // 递归调用,尝试不放入第i个物品
}
}
}
// 定义输出最优解的函数
void dispasolution() {
int i;
for (i = 1; i <= n; i++) {
if (x[i] == 1) {
printf("%d ", i); // 输出被选中的物品编号
}
}
printf("\n%d %d", W, maxv); // 输出背包限制重量和最优解的总价值
}
int main() {
int i;
cin >> n >> W; // 输入物体个数和背包载重量
for (int i = 1; i <= n; i++) { // 输入各物体的重量和价值
cin >> w[i] >> v[i];
}
int op[MAXN]; // 定义临时解数组
memset(op, 0, sizeof(op)); // 初始化临时解数组为0
int rw = 0; // 计算所有物品的总重量
for (int i = 1; i <= n; i++) {
rw += w[i];
}
dfs(1, 0, 0, rw, op); // 调用求解函数
dispasolution(); // 调用输出函数
return 0;
}
本文介绍了如何使用递归方法解决0/1背包问题,给出了一段C++代码实例,展示了如何在给定背包容量和物品价值的情况下选择物品以达到最大价值。
805

被折叠的 条评论
为什么被折叠?



