要求:体重量刚好等于最大重量时的价值(tw = W)
一:最基本想法,遍历整个解空间树(所有子集解的集合)
void dfs(int i, int tw,int tv,int op){
//找到一个解
if(i>n){
if(tw==W&&tv>maxv){
maxv = tv;
for(int j=0;j<n;j++)
x[j]=op[j];
}
}
op[i]=1,dfs(i+1,tw+w[i],tv+v[i],op);
op[i]=0,dfs(i+1,tw,tv,op);
}
二:左子树(设置约束条件)
后面要选的物品 重量不超才选 tw+t [ i ] <= W
void dfs(int i, int tw,int tv,int op){
//找到一个解
if(i>n){
if(tw==W&&tv>maxv){
maxv = tv;
for(int j=0;j<n;j++)
x[j]=op[j];
}
}
if(tw+t[i]<=W) //删除重量超过的物品,后面的物品都不用选择了
op[i]=1,dfs(i+1,tw+w[i],tv+v[i],op),op[i]=0;//回溯
dfs(i+1,tw,tv,op);
}
三:右子树(限定条件)
tw + rw -w[ i ]>= W //剩余重量若是 < 背包重量,选与不选的意义不大,重量都不会 = 背包重量
//改进(右子树限定条件)
void dfs(int i, int tw,int tv,int rw, int op){
//找到一个解
if(i>n){
if(tw==W&&tv>maxv){
maxv = tv;
for(int j=0;j<n;j++)
x[j]=op[j];
}
}
if(tw+t[i]<=W)
op[i]=1, dfs(i+1,tw+w[i],tv+v[i],rw,op),op[i]=0;//回溯
//最难理解的,当不选择物品i时,rw - w[i]=w[i+1]+w[i+2]...w[n],
//若tw + rw -w[i] < W 说明不会选择后面的所有物品
//不会选择是指右子树的左右子树都不会在选择了。
if(tw+rw-w[i]>=W)
dfs(i+1,tw,tv, rw-w[i], op);
}
要求:物体重量和不超过最大W , 保证价值最大
左剪枝不变,始终选的重量小于W
右剪枝后面的价值大于MAXV
void dfs(int i, int tw,int tv, int op){
//找到一个解
if(i>n){
maxv = tv;
for(int j=0;j<n;j++)
x[j]=op[j];
}
}
if(tw+t[i]<=W)
op[i]=1, dfs(i+1,tw+w[i],tv+v[i],rw,op),op[i]=0;//回溯
if(tv + rv-v[i]>maxv)
dfs(i+1,tw,tv, op);
}
以上内容仅供个人学习参考