一、问题描述
给你 i 个物品,每个物品都具有两个属性(价值value[ i ]和重量weight[ i ]),将他们放入容量为 j 的背包中(不可以重复放入同一个物品),怎么放才能让背包的价值最大?
二、代码实现
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct
{
int weight;
int value;
}thing;
int n,c;
int cw = 0,cv = 0;//cw:当前重量 cv: 当前价值
int bestv = 0;//当前最优价值
thing *things;
float Bound(int i);
void backtrack(int i);
bool cmp(thing a,thing b);
int main()
{
cin >> n >> c;
things = new thing[n];
for(int i=0;i<n;i++){
cin >> things[i].weight >> things[i].value;
}
sort(things,things+n,cmp);
backtrack(0);
cout << bestv;
delete things;
return 0;
}
bool cmp(thing a,thing b)
{
if(float(a.value)/a.weight > float(b.value)/b.weight)
return true;
else return false;
}
void backtrack(int i)
{
if(i >= n){//到达叶子节点
if(cv > bestv) bestv = cv;
return;
}
if(cw + things[i].weight <= c){//装入背包,进入左子树
cw += things[i].weight;
cv += things[i].value;
backtrack(i+1);
cw -= things[i].weight;
cv -= things[i].value;//回溯
}
if(Bound(i+1) > bestv)//不装包,进入右子树
backtrack(i+1);
}
float Bound(int i)
{
int cleft = c - cw;//剩余容量
int b = cv;
while(i < n && things[i].weight <= cleft)
{//以物品单位重量价值递减序装入物品
b += things[i].value;
cleft -= things[i].weight;
i++;
}
//装满背包
if(i < n)
b += things[i].value * cleft/things[i].weight;
return b;
}