1.有N个物品,每个物品都有重量和价格,在不超过背包容量V的情况下选出价格之和最大,求最大价值maxValue。
思路,每个物品都有2种方法,选择或不选择,相当于迷宫的岔路口,递归中的递归式。而当物品总重量超过背包容量V,在相当于迷宫中的死胡同,递归中的递归边界。通过枚举所有选择方案,来得出最优解。
其中DFS是常规解,DFS_better是用了剪枝技巧的优化解
#include <cstdio>
using namespace std;
const int maxn = 30;
int n,V,maxValue = 0;
int w[maxn],c[maxn];
//index为当前物品编号,sumW,sumC为当前的总重量和总价值
void DFS(int index, int sumW, int sumC){
if(index == n){ //当完成对n个物品的选择,把最大价值给输出
if( sumW <= V && sumC > maxValue){
maxValue = sumC;
}
return ;
}
//岔道口,选择还是不选择
DFS( index+1, sumW, sumC); //不选择第index号物品,index(0~n-1);
DFS( index+1, sumW+w[index], sumC+c[index]); //选择第index号物品,则加上其重量和价值
}
//优化后的
void DFS_better(int index ,int sumW, int sumC){
if(index == n) return;
DFS(index+1, sumW,sumC);
if(sumW + w[index] <= V){ //若将当前第index号物品加入后不超过总容量才进行选择
if(sumC +c[index] > maxValue){
maxValue = sumC + c[index];
}
DFS(index+1, sumW + w[index],sumC + c[index]);
}
}
int main(){
scanf("%d%d", &n,&V);
for(int i=0; i<n; i++)
scanf("%d" , &w[i]) ;
for(int i=0; i<n; i++)
scanf("%d", &c[i]);
DFS_better(0,0,0); //从第0号物品开始选择
printf("%d",maxValue);
return 0;
}
这适用于一类DFS问题的解决方法,即给定一个序列,枚举这个序列的所有子序列(可以不连续)。例如对序列{1,2,3)来说,它的所有子序列为{I}、 {2}、 {3)、 {1,2}、{1,3}、 {2,3)、{1,2,3)。枚举所有子序列的目的很明显―可以从中选择一个 “最优”子序列,使它的某个特征是所有子序列中最优的;如果有需要,还可以把这个最优子 序列保存下来。显然,这个问题也等价于枚举从N个整数中选择K个数的所有方案。