题目:一辆购物车容量为W,总共有n个物品,第i个物品对应价值vi,重量wi,不可拆分,如何选取物品使购物车装入物品价值最大。
解题思路:本题很直观的用贪心解决比较简单,但这借此写一下回溯算法。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define M 105
int i,j,n,W; //n表示物品数量,W表示购物车容量
double w[M],v[M]; //重量,价值
bool x[M]; //x[i]=1表示第i个物品放进购物车
double cw=0; //当前重量
double cp=0; //当前价值
double bestp=0; //当前最优值
bool bestx[M]; //最优解
double Bound(int i) //计算剩余物品装满时所能获得最大价值
{
double cleft=W-cw;
double brp=0.0;
while(i<=n&&w[i]<cleft)
{
cleft-=w[i];
brp+=v[i];
i++;
}
if(i<=n) //采用分割方式求上界,但求解时不允许
{
brp+=v[i]/w[i]*cleft;
}
return brp+cp;
}
void Backtrack(int t) //搜索空间,t表示在t层
{
if(t>n) //已经到达最底层叶子节点
{
for(j=1;j<=n;j++)
bestx[j]=x[j];
bestp=cp;
return ;
}
if(cw+w[t]<=W) //满足条件则搜索左节点
{
x[t]=1;
cw+=w[t];
cp+=v[t];
Backtrack(t+1);
cw-=w[t];
cp-=v[t];
}
if(Bound(t+1)>bestp) //满足条件则搜索右节点
{
x[t]=0;
Backtrack(t+1);
}
}
int main()
{
cin>>n>>W;
double sumw=0.0;
double sumv=0.0;
for(i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
sumw+=w[i];
sumv+=v[i];
}
if(sumw<=W)
cout<<sumv<<endl;
else
Backtrack(1);
cout<<bestp<<endl;
for(i=1;i<=n;i++)
if(bestx[i]==1)
printf("%d ",i);
return 0;
}