描述:
需对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。
输入:
多个测例,每个测例的输入占三行。第一行两个整数:n(n<=10)和c,第二行n个整数分别是w1到wn,第三行n个整数分别是p1到pn。
n 和 c 都等于零标志输入结束。
输出:
每个测例的输出占一行,输出一个整数,即最佳装载的总价值。
输入样例:
1 2 1 1 2 3 2 2 3 4 0 0
输出样例:
1 4
#include <iostream>
#include <algorithm>
using namespace std;
double c; //背包容量
int n; //物品数
double cw; //当前重量
double cp; //当前价值
int bestp; //当前最优价值
typedef struct Item
{
double w; //物品的重量
double p; //物品的价值
}Item;
Item item[100];
bool cmp(Item a, Item b)
{
return a.p/a.w > b.p/b.w;
}
double bound(int i)
{
double cleft = c - cw; //剩余容量
double b = cp; //能装载容量的最大上界
//将剩余物品装入背包,直至装不下为止
while(i <= n && item[i].w <= cleft)
{
cleft -= item[i].w;
b += item[i].p;
}
//将最后一件装不下的物品拆解,让背包装满
//计算能装载容量的最大上界
if(i <= n)
b += item[i].p/item[i].w*cleft;
return b;
}
void Backtrack(int i)
{
//叶子节点
if(i > n)
{
if(cp > bestp) //上界不一定取到
bestp = (int)cp;
//cout << "bestp " << bestp << endl;
return;
}
//搜索子树
if(cw + item[i].w <= c)
{
cw += item[i].w;
cp += item[i].p;
//cout <<"cw =" << cw <<"cp ="<< cp << endl;
Backtrack(i+1);
cw -= item[i].w;
cp -= item[i].p;
//cout <<"cw =" << cw <<"cp ="<< cp << endl;
}
if(bound(i+1) > bestp)
Backtrack(i+1);
}
int main()
{
while(cin >> n >> c && (n || c))
{
bestp = 0; //每组样例初始化
for(int i = 1; i <= n; i ++) //i从1开始
cin >> item[i].w;
for(int i = 1; i <= n; i ++)
cin >> item[i].p;
sort(item+1, item+n+1, cmp); //从1开始,wa了好多次
Backtrack(1); //从1开始递归
printf("%d\n", bestp);
}
return 0;
}