You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
domitory/分支限界法算法设计.cpp

56 lines
1.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
const int N = (1 << 20) + 10;
int n,m;
int v[N],w[N];
int res = -1;
int s[N]; // s[i]存储的是从第1件物品到第i件物品的价值总和
struct good{
int idx,c,r,tv; // idx表示选法下标c表示该选法的当前总价值r表示当前选法的剩余总价值tv表示该选法的当前总体积
bool operator > (const good& W) const{
return W.c + W.r > c + r;
}
}goods[N];
int bfs(){
goods[1] = {1,0,0,0};
priority_queue<good,vector<good>,greater<good>> q;
q.push(goods[1]);
while(q.size()){
auto t = q.top();
// cout << t.idx << endl;
q.pop();
int idx = t.idx << 1;
goods[idx] = {idx,goods[t.idx].c,s[n] - s[(int)log2(idx)],goods[t.idx].tv};
goods[idx + 1] = {idx + 1,goods[t.idx].c + w[(int)log2(idx)],s[n] - s[(int)log2(idx)],goods[t.idx].tv + v[(int)log2(idx)]};
if((int)log2(t.idx) == n) { // 假如已经是子节点,则更新答案
res = max(res,t.c);
continue;
}
if(goods[idx].tv <= m && goods[idx].c + goods[idx].r > res) q.push(goods[idx]); // 假如当前选法的总体积不超过背包容量,且当前价值+剩余价值 > 当前最优解,则装入背包
if(goods[idx + 1].tv <= m && goods[idx + 1].c + goods[idx + 1].r > res) q.push(goods[idx + 1]);
}
return res;
}
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i],s[i] = s[i - 1] + w[i];
//
// for(int i = 2; i < 1 << n + 1; i ++){
// goods[i] = {i,goods[i >> 1].c + (i&1)*w[(int)log2(i)],s[n] - s[(int)log2(i)],goods[i >> 1].tv + (i&1)*v[(int)log2(i)]};
// }
//
// for(int i = 1; i < 1 << n + 1; i ++) printf("i = %d,c[i] = %d,r[i] = %d,tv[i] = %d\n",goods[i].idx,goods[i].c,goods[i].r,goods[i].tv);
cout << bfs() << endl;
return 0;
}