一,题目:7-1 0-1背包 (40 分)
给定n(n<=100)种物品和一个背包。物品i的重量是wi,价值为vi,背包的容量为C(C<=1000)。问:应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品i装入多次,也不能只装入部分物品i。
输入格式:
共有n+1行输入: 第一行为n值和c值,表示n件物品和背包容量c; 接下来的n行,每行有两个数据,分别表示第i(1≤i≤n)件物品的重量和价值。
输出格式:
输出装入背包中物品的最大总价值。
输入样例:
5 10
2 6
2 3
6 5
5 4
4 6
输出样例:
15
二、代码
#include<iostream>
using namespace std;
int n,c;
int cv=0; // 当前价值
int cw=0; // 当前可用重量
int x[100]; // 选物品情况
int w[100],v[100]; //各个物品重量价值
int maxV=0; // 记录最大的价值
//限界函数,可以减少递归次数
int bound(int t){
int sum;
for(int i=t;i<n+1;i++)
sum+=v[i];
return sum;
}
//回溯函数
void Backtrack(int t){ // t为深度,从 1 开始
if(t>n){ // 达到叶子结点,即判断完所有物品选择情况,退出递归
if(cv>maxV) // 判断当前价值是否最大
maxV=cv;
return;
}
if(w[t]<=cw){
//选当前物品,左子树
x[t]=1; // 选择置1
cw-=w[t]; // 重量减去选的物品重量
cv+=v[t]; // 价值加上选的物品价值
Backtrack(t+1); // 继续往左子树下走
cw+=w[t]; // 回溯,重量一一加回来
cv-=v[t];// 回溯,价值一一减回去
}
//限界函数
if(bound(t+1)>maxV){
x[t]=0;
Backtrack(t+1);
}
}
int main(){
cin>>n>>c;
cw=c;
for(int i=1;i<=n;i++){ //从1位置开始输入,0位置不记录
cin>>w[i]>>v[i];
}
Backtrack(1);
cout<<maxV<<endl;
return 0;
}