0/1背包问题。给定一载重量为W的背包及n个重量为wi、价值为vi的物体,1≤i≤n,要求重量和恰好为W具有最大的价值。
输入格式:
第一行输入背包载重量W及背包个数n,再依次输入n行,每行为背包重量wi和价值vi。
输出格式:
第一行输出装入背包内的物体编号(末尾有空格),若没有任何物品能装入,输出: No,第二行输出背包内的物体总价值。
输入样例1:
5 10
2 6
2 3
6 5
5 4
4 6
输出样例1:
1 2 3
14
输入样例2:
2 10
11 2
13 100
输出样例2:
No
0
代码如下:
#include <bits/stdc++.h>
using namespace std;
int C,N;//背包剩余容量,物体数量
int w[105],v[105];//物体重量,价值
int cw=0;//当前背包重量
int cv=0;//当前总价值
int len=1;//当前选择长度
int best_len=1;//最佳选择长度
int best=0;//最大价值
int result[105];//当前物品编号
int best_result[105];//最有选择物品编号
//限界函数(背包的贪心算法)
int Bound(int i)
{
int rw=C-cw;//剩余容量
int value=cv;//当前背包价值
//假设把剩下的物品全加入背包
while(i<=N && w[i]<=rw)
{
rw-=w[i];
value+=v[i];
i++;
}
//装满背包,求出若将剩余物品全部加入背包所达到的价值上限
if(i<=N)
{
value+=v[i]/w[i]*rw;//v[i]/w[i]为性价比
}
return value;
}
void dfs(int k)
{
//若递归搜索层次超过物体数量,终止
if(k>N && cw==C && cv>best)
{
best=cv;
best_len=len;
for(int i=1;i<len;i++)
{
best_result[i]=result[i];
}
return ;
}
//如果背包容量足够装下该物品
if(cw+w[k]<=C)//进入左子树
{
cw+=w[k];//当前背包重量
cv+=v[k];//当前价值增加
result[len]=k;
len++;
k++;
dfs(k);
//回溯
k--;
len--;
result[len]=0;
cw-=w[k];
cv-=v[k];
}
//若不装该物品,考虑当前价值+剩余物品价值最大上限(若全部加入背包)是否比best大
if(Bound(k+1)>best)//进入右子树
{
k++;
dfs(k);
k--;
}
}
int main()
{
cin>>N>>C;
for(int i=1;i<=N;i++)
cin>>w[i]>>v[i];
dfs(1);
if(best==0)
{
cout<<"No"<<endl;
cout<<0<<endl;
}
else
{
for(int i=1;i<best_len;i++)
cout<<best_result[i]<<" ";
cout<<endl;
cout<<best<<endl;
}
return 0;
}