使用优先队列,求最大价值
首先按照性价比排序
bound函数表示当前状态之后的选择都是理想的,这样能到达的理想最大值
每个节点存储物品在树中的层次,表示已经对多少个物品做出了选择,当前状态放入背包的总价值和重量。
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
struct stone{
int v, w;
stone(){
v = w = 0;
}
bool operator < (stone b) const {
return v/w > b.v/b.w;
}
}item[N];
struct node{
int level, cv, cw;
float bound;
bool operator< (const node& b) const{
return bound > b.bound;
}
};
int best, W, n;
inline void Initialize(priority_queue<node> &Q){
while(Q.size()) Q.pop();
}
float bound(node& p){
int left = W-p.cw;
float val = p.cv;
int i;
for(i = p.level; i <= n && item[i].w <= left; i++){
left -= item[i].w;
val += item[i].v;
}
if(i <= n) val += item[i].v*1.0/item[i].w*left;
return val;
}
priority_queue<node> PQ;
void knapsack(){
node u, v;
Initialize(PQ);
v = {0,0,0,0};
best = 0;
v.bound = bound(v);
PQ.push(v);
while(PQ.size()){
v = PQ.top();
PQ.pop();
if(v.level == n) continue;
if(v.bound > best){
u.level = v.level+1;
u.cw = v.cw+item[u.level].w;
u.cv = v.cv+item[u.level].v;
//printf("%d %d\n", u.cw, u.cv);
if(u.cw <= W && u.cv > best)
best = u.cv;
u.bound = bound(u);
if(u.bound > best) PQ.push(u);
u.cw = v.cw; u.cv = v.cv;
u.level = v.level+1;
u.bound = bound(u);
if(u.bound > best) PQ.push(u);
}
}
}
int main(){
scanf("%d%d", &n, &W);
for(int i = 1; i <= n; i++) scanf("%d", &item[i].w);
for(int i = 1; i <= n; i++) scanf("%d", &item[i].v);
sort(item+1, item+1+n);
knapsack();
printf("%d\n", best);
return 0;
}
/*
4 7
3 5 2 1
9 10 7 4
20
*/