#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 cnt[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 Solution(int i)
{
while(i >= 0)//当层数i < 0时退出根节点退出循环
{
/*
cnt数组存储访问该层节点的次数:
当cnt[i]为0时即第一次访问,进入左子树;
当cnt[i]为1时即第二次访问,进入右子树
当cnt[i]大于1时说明该节点的左右子树均被访问,退出该层节点i--
*/
if(cnt[i] <= 1)
{
for(int j = cnt[i]; j <= 1; j++)//即 cnt[i]从0 ~ 1依次查找左右子树
{
if(i == n)//搜到叶子结点,更新bestp
{
bestp = cp;
bestw = cw;
i--;
}
int child = 1 - cnt[i];
/*
当cnt[i]为0时,child为1即访问左子树
当cnt[i]为1时,child为0即访问右子树
*/
if(child)
{ //满足约束函数进入左子树
if(cw + objects[i].w <= c)
{
objects[i].flag = true;
cw += objects[i].w;
cp += objects[i].p;
cnt[i]++;
i++;
}
else
cnt[i]++;//即使无法访问左子树,即以该结点为根的子树被剪掉,但这也说明当前扩展结点的左儿子已被访问
}
else
{
//满足限界函数进入右子树
if(Bound(i + 1) > bestp)
{
cnt[i]++;
i++;
}
else
cnt[i]++;//即使无法进入右子树,即以该结点为根的子树被剪掉,但这也说明当前扩展结点的右儿子已被访问
}
}
}
else
{
//当cnt[i] > 1时即cnt[i] == 2时,说明当前扩展结点的左右子树均已被访问则按照dfs规则向上回溯,返回上一层
cnt[i] == 0;//将cnt[i]重新设置为0,使得下一次进入该层使为第一次进入.
i--; //回溯
}
}
}
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); //按物品单位重量价值非递减排序
Solution(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
*/