1、树形结构的应用
当需要求解的问题是从N个元素所构成的全集U中找寻满足问题条件的子集时,相应的解空间树称为子集树,在对子集树进行深度优先遍历时储存所经过边的数值,1表示包含该元素,0表示不包含改元素,当遍历到叶子节点时输出这由0与1组成且有N位的字符串,这样一来深度优先遍历完这棵树就能得到其全集U的所有子集,也是求解0-1背包问题会遇到的所有情况。
2、回溯法求解思想
我们在用深度优先搜索子集树时并不是非要遍历完每一种情况,在遍历途中利用剪枝条件可以减少代码语句执行次数,回溯法就是在搜索最优解的途中避免无效搜索的一种优化算法。
3、具体代码和现
#include <stdio.h>
#include <stdlib.h>
const int N=10;
const int bag=N*2;
struct goods{
int w;
int v;
}g[N];
int max_value=0;
int a[N],r[N+1],x[N];
int huisu(int count,int now_v,int now_w);
int main(){
int i;
for (i = 0; i < N; i++) {
g[i].v = rand() % 5 + 1;
g[i].w = rand() % 5 + 1;
printf("物品%d,价值%d,重量%d\n", i, g[i].v, g[i].w);
}
r[N] = 0;
for (i = N - 1; i >= 0; i--) {
r[i] = r[i + 1] + g[i].v;
}
int maxv = huisu(0, 0, 0);
printf("装入的物品是:\n");
int w=0;
for(int i=N-1;i>=0;i--){
if(x[i]==1){
printf("%d ",i);
}
}
printf("\n能获得的最大价值为:%d", maxv);
return 0;
}
int huisu(int count,int now_v,int now_w)
{
if(count==N){
if(now_w<=bag&&now_v>max_value){
max_value=now_v;
for(int j=0;j<N;j++){
x[j]=a[j];
}
}
}
else{
for(int i=0;i<=1;i++){
a[count]=i;
now_v=now_v+g[count].v*i;
now_w=now_w+g[count].w*i;
if(now_w<=bag&&now_v+r[count+1]>=max_value)
huisu(count+1,now_v,now_w);
}
}
return max_value;
}