问题描述:装入背包中物品重量和恰好为W
解法一
#include<stdio.h>
#define MAXN 20 // 最多物品数
// 问题表示
int n = 4; // 4种物品
int W = 6; // 限制重量为6
int w[] = {0, 5, 3, 2, 1}; // 存放4个物品重量,不用下标0元素
int v[] = {0, 4, 4, 3, 1}; // 存放4个物品价值,不用下标0元素
// 求解结果表示
int x[MAXN]; // 存放最终解
int maxv = 0; // 存放最优解的总价值
void dfs(int i, int tw, int tv, int op[]){ // 求解0/1背包问题
if(i > n){ // 找到一个叶子节点
if(tw == W && tv > maxv){ // 找到一个满足条件的更优解,保持它
maxv = tv;
for(int j = 1; j <= n; j++)
x[j] = op[j];
}
}
else {
op[i] = 1; // 尚未找完所有物品
dfs(i+1, tw+w[i],tv+v[i],op);
op[i] = 0;
dfs(i+1, tw, tv, op);
}
}
void dispasolution(){ // 输出最优解
printf("最佳装填方案:\n");
for(int i = 0; i <= n; i++){
if(x[i] == 1)
printf(" 选取第%d个物品\n",i);
}
printf("总重量=%d,总价值=%d\n",W,maxv);
}
int main(){
int op[MAXN]; // 存放临时解
dfs(1,0,0,op); // i从1开始
dispasolution();
return 0;
}
解法二:左剪枝
#include<stdio.h>
#define MAXN 20 // 最多物品数
// 问题表示
int n = 4; // 4种物品
int W = 6; // 限制重量为6
int w[] = {0, 5, 3, 2, 1}; // 存放4个物品重量,不用下标0元素
int v[] = {0, 4, 4, 3, 1}; // 存放4个物品价值,不用下标0元素
// 求解结果表示
int x[MAXN]; // 存放最终解
int maxv = 0; // 存放最优解的总价值
void dfs(int i, int tw, int tv, int op[]){ // 求解0/1背包问题
if(i > n){ // 找到一个叶子节点
if(tw == W && tv > maxv){ // 找到一个满足条件的更优解,保持它
maxv = tv;
for(int j = 1; j <= n; j++)
x[j] = op[j];
}
}
else { // 尚未找完所有物品
// 解法一
// op[i] = 1;
// dfs(i+1, tw+w[i],tv+v[i],op);
// 解法二,左剪枝
if(tw+w[i] <= W){ // 左孩子结点剪枝
op[i] = 1; // 选取第i个物品
dfs(i+1, tw+w[i],tv+v[i],op);
}
op[i] = 0; // 不选取第i个物品,回溯
dfs(i+1, tw, tv, op);
}
}
void dispasolution(){ // 输出最优解
printf("最佳装填方案:\n");
for(int i = 0; i <= n; i++){
if(x[i] == 1)
printf(" 选取第%d个物品\n",i);
}
printf("总重量=%d,总价值=%d\n",W,maxv);
}
int main(){
int op[MAXN]; // 存放临时解
dfs(1,0,0,op); // i从1开始
dispasolution();
return 0;
}
解法三:右剪枝
#include<stdio.h>
#define MAXN 20 // 最多物品数
// 问题表示
int n = 4; // 4种物品
int W = 6; // 限制重量为6
int w[] = {0, 5, 3, 2, 1}; // 存放4个物品重量,不用下标0元素
int v[] = {0, 4, 4, 3, 1}; // 存放4个物品价值,不用下标0元素
// 求解结果表示
int x[MAXN]; // 存放最终解
int maxv = 0; // 存放最优解的总价值
void dfs(int i, int tw, int tv, int rw, int op[]){ // 求解0/1背包问题
if(i > n){ // 找到一个叶子节点
if(tw == W && tv > maxv){ // 找到一个满足条件的更优解,保持它
maxv = tv;
for(int j = 1; j <= n; j++)
x[j] = op[j];
}
}
else { // 尚未找完所有物品
// 解法一
// op[i] = 1;
// dfs(i+1, tw+w[i],tv+v[i],op);
// 解法二:左剪枝
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个物品,回溯
// dfs(i+1, tw, tv, op);
// 解法三:右剪枝
if(tw + rw - w[i] >= W){ // 右孩子结点剪枝
op[i] = 0; // 不选取第i个物品,回溯
dfs(i+1, tw, tv, rw-w[i], op);
}
}
}
void dispasolution(){ // 输出最优解
printf("最佳装填方案:\n");
for(int i = 0; i <= n; i++){
if(x[i] == 1)
printf(" 选取第%d个物品\n",i);
}
printf("总重量=%d,总价值=%d\n",W,maxv);
}
int main(){
int op[MAXN]; // 存放临时解
int rw=0;
for(int i=1;i<=n;i++)
rw+=w[i];
dfs(1,0,0,rw,op); // i从1开始
dispasolution();
return 0;
}
运行结果