#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
using namespace std;
const int N=100;
int w[N];//记录物品重量
int v[N];//记录物品价值
int W;//背包最大容量
int n;//物品个数
int bestv;//当前记录最优价值
int aa[N];//存放真正的最佳选择(未排序前)
string bestx; //最优价值的选择 (排序后)
//借助 VW结构体 辅助按照性价比放入最大堆
struct VW{
int value;
int weight;
double cp;//性价比
int num;//记录原来位置
};
struct VW vw[N];
//根据性价比排序
bool cmpvw(struct VW &x,struct VW &y){
return x.cp>y.cp;
}
//建立解空间树的节点
struct node{
int cv;//当前所装入物品的价值
int cw;//当前所装入物品的重量
int count;//当前到达第几个物品
double maybe;//预计最大价值
string choose;//记录选择路线(排好序的)
};
将vw放入优先队列不合适
//我们在取数据时并不能保证时按照最佳性价比的排序去数据
//struct cmpvw{
// bool operator()(struct VW &x,struct VW &y){
// return x.cp < y.cp;//"<"从大到小排 ">"从小到大排
// }
//};
//priority_queue<VW,vector<VW>,cmpvw> qvw;
//最大堆
struct cmp{
bool operator()(struct node &x,struct node &y){
return x.maybe<y.maybe;
}
};
//通过该函数获得可能的最大值
double getmaybe(struct node x){
int xw=W-x.cw;
double may=x.cv;
for(int i=x.count+1;i<=n;i++){
if(xw>=vw[i].weight){
may=may+vw[i].value;
xw=xw-vw[i].weight;
}
else{
may=may+xw*vw[i].cp;
break;
}
}
return may;
}
int main(){
cin>>n>>W;//输入物品个数,背包最大承重
//依次输入物品的重量与价值
for(int i=1;i<=n;i++){
cin>>w[i];
}
for(int i=1;i<=n;i++){
cin>>v[i];
}
//将物品的价值与重量放入vw结构体数组
for(int i=1;i<=n;i++){
vw[i].value=v[i];
vw[i].weight=w[i];
vw[i].cp=1.0*vw[i].value/vw[i].weight;
vw[i].num=i;
}
//按照性价比排序
sort(vw+1,vw+n+1,cmpvw);
//检查
// for(int i=1;i<=n;i++){
// cout<<vw[i].value<<" "<<vw[i].weight<<endl;
// }
/*
测试样例
5 15
1 2 3 4 5
5 16 21 4 50
5 8 7 1 10
5 10
2 2 6 5 4
6 3 5 4 6
*/
priority_queue<node,vector<node>,cmp> q;
//将vw放入优先队列不合适
// //将vw结构体数组放入qvw堆中
// for(int i=1;i<=n;i++){
// qvw.push(vw[i]);
// }
//
// //检查一下 qvw最大堆
// while(!qvw.empty()){
// struct VW x=qvw.top();
// cout<<x.value<<" "<<x.weight<<endl;
// qvw.pop();
// }
//准备工作完成,进行求解
bestv=0;
node a;
a.count=0;a.cv=0;a.cw=0;a.maybe=getmaybe(a);a.choose=" ";
// cout<<a.maybe<<endl;
q.push(a);node x;
while(!q.empty()){
x=q.top();q.pop();
if(x.cv>=bestv){
bestv=x.cv;
// cout<<x.choose<<endl;
bestx=x.choose;
}
if(x.maybe<bestv)continue;
//当count层数小于n时,扩展节点
if(x.count<n){
//左节点 选择
node l;
l.count=x.count+1;
l.cv=x.cv+vw[l.count].value;
l.cw=x.cw+vw[l.count].weight;
l.maybe=getmaybe(l);
l.choose=x.choose+"1";
//只有maybe大于当前最大时,才能放入队列
if(l.maybe>=bestv&&l.cw<=W) q.push(l);
//右节点 不选
node r;
r.count=x.count+1;
r.cv=x.cv;
r.cw=x.cw;
r.maybe=getmaybe(r);
r.choose=x.choose+"0";
//只有maybe大于当前最大时,才能放入队列
if(r.maybe>=bestv&&r.cw<=W) q.push(r);
}
}
cout<<bestv<<endl;
//获取最佳选择
//cout<<bestx<<endl;
for(int i=1;i<=n;i++){
if(bestx[i]=='1'){
aa[vw[i].num]=1;
}
}
//输出最佳选择
for(int i=1;i<=n;i++){
cout<<aa[i]<<" ";
}
cout<<endl;
}
//BFS模板
//void bfs(int s){
// queue<int >q;
// q.push();
// while(!q.empty()){
// q.top();
// .....
// x.push();
// }
//}
0-1背包问题(分支限界法)
最新推荐文章于 2024-06-02 19:27:48 发布