问题描述:假设有7个物品,它们的重量和价值如下表所示。若这些物品均不能被分割,且背包容量C=150,使用回溯方法求解此背包问题
物品 | A | B | C | D | E | F | G |
重量 | 35 | 30 | 60 | 50 | 40 | 10 | 25 |
价值 | 10 | 40 | 30 | 50 | 35 | 40 | 30 |
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int n; //物品数量
int c; //背包容量
int cw; //当前背包重量
int cp; //当前背包装入物品价值
int bestp; //装包最大价值
int bestw; //最大价值时的背包重量
struct object{
char id; //物品编号
int p; //物品价值
int w; //物品重量
double pw; //单位重量价值
bool flag;
}objects[100];
//上界函数
int Bound(int i)
{
int cleft = c - cw; //当前背包剩余容量
double b = cp;
while(i < n && objects[i].w <= cleft)
{
cleft -= objects[i].w;
b += objects[i].p;
i++;
}
if(i < n)
b += (1.0 * cleft) / objects[i].w * objects[i].p;
return b;
}
bool cmp(struct object a, struct object b)
{
return a.pw > b.pw;
}
void Backtrack(int i)
{
//搜到叶子结点,更新bestp
if(i == n)
{
bestp = cp;
bestw = cw;
return;
}
//满足约束函数进入左子树
if(cw + objects[i].w <= c)
{
objects[i].flag = true;
cw += objects[i].w;
cp += objects[i].p;
Backtrack(i + 1);
cw -= objects[i].w;
cp -= objects[i].p;
}
//满足限界函数进入右子树
if(Bound(i + 1) > bestp)
Backtrack(i + 1);
}
int main()
{
int sum_p = 0, sum_w = 0;
cin >> n >> c;
for(int i = 0; i < n; i++)
{
cin>>objects[i].id;
objects[i].flag = false;
}
for(int i = 0; i < n; i++)
{
cin >> objects[i].w;
}
for(int i = 0; i < n; i++)
{
cin >> objects[i].p;
}
for(int i = 0; i < n; i++)
{
sum_p += objects[i].p;
sum_w += objects[i].w;
objects[i].pw = (1.0 * objects[i].p) / objects[i].w;
}
if(sum_w <= c)
{
cout << "背包能全装下" << endl;
cout << "价值为:" << sum_p << endl;
return 0;
}
sort(objects, objects + n, cmp); //按物品单位重量价值非递减排序
Backtrack(0);
cout << "装入背包的物品有:" << endl;
for(int i = 0; i < n; i++)
{
if(objects[i].flag == true)
cout << objects[i].id << " ";
}
cout << endl;
cout << "物品装包最大价值为:" << endl;
cout << bestp << endl;
cout << "装包价值最大时,物品重量为:" << endl;
cout << bestw << endl;
return 0;
}
/*
测试:
7 150
A B C D E F G
35 30 60 50 40 10 25
10 40 30 50 35 40 30
*/