C语言,回溯法0-1背包问题

回溯法0-1背包问题

本文以 http://blog.sina.com.cn/s/blog_690e57390100khgl.html 为主题编写的回溯0-1背包问题

1、问题描述
物品总数量为n,背包容量为v,物品价值分别为value(……),物品重量为weight(…….),求如何存放物品使背包价值最大。

2、回溯算法思路

  • 初始化数据后,我们先从第一个物品存入到背包中,
  • 判断物品是否已经使用完毕。如何使用完,判断是否当前价值量大于原有最大价值量,如果大于将最大价值量替换,标记放入的物品,否则不做修改
  • 随后,我们判断是否物品存入超出了背包总容积,如果没有将背包现
    在容积以及价值量相加,设置标志已放入背包,保存,随后将下一个背包存放测试,跳转到2
  • 第3步内为一直测试二叉树的左子树,当到达最底部左子树后,回溯到上一结点,现存容积与价值量减去当前结点重量与价值量,进行该结点右子树循环查找,直到第2步返回
  • 回溯结束,跳转到主函数输出结果

以下为VC6.0 下所写代码

#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h" 
#include "string.h" 


typedef struct {

int number;       //物品总数量
int volume;       //背吧容量
int curValue;     //背包现存价值
int curVolume;    //背包现存容量
int* curBackpack; //背包内存放物品数组,curPackage[i] = 1; 为已 经放入背包中 
                  // = 0; 为未放入背包中
int maxValue;     //背包最大价值量
int* lastBackpack;//最优解背包内物品
int* goodsValue;  //物品价值数组
int* goodsWeight; //物品重量数组
}Backpack;


Backpack bp;

void initBackpack(int v, int n){

    bp.number = n;
    bp.volume = v;
    bp.curValue = 0;
    bp.curVolume = 0;
    bp.maxValue = 0;

    bp.goodsValue = (int*)malloc(bp.number * sizeof(int));
    memset(bp.goodsValue, 0, bp.number * (sizeof(int)));
    bp.goodsWeight = (int*)malloc(bp.number * sizeof(int));
    memset(bp.goodsWeight, 0, bp.number * (sizeof(int)));
    bp.curBackpack = (int*)malloc(bp.number * sizeof(int));
    memset(bp.curBackpack, 0, bp.number * (sizeof(int)));
    bp.lastBackpack = (int*)malloc(bp.number * sizeof(int));
    memset(bp.lastBackpack, 0, bp.number * (sizeof(int)));

    for(int j=0;j < bp.number;j++){
        printf("请输入第%d个物品价值:",(j+1));
        scanf("%d",&bp.goodsValue[j]);
        printf("请输入第%d个物品重量:",(j+1));
        scanf("%d",&bp.goodsWeight[j]);
    }

}


void backTrace(int position){
    if((position+1) > bp.number){
        //当物品全部测试后,查看最大价值量,如何新的价值量大于上一次价值量
        //替换掉,并记忆存放的物品
        if(bp.curValue > bp.maxValue){
            bp.maxValue = bp.curValue;      
            for(int i=0;i < bp.number;i++){
                bp.lastBackpack[i] = bp.curBackpack[i];
            }
        }
        return;
    }

    //需要通过二叉树图一步步了解回溯
    if((bp.curVolume + bp.goodsWeight[position]) <= bp.volume){
        bp.curVolume += bp.goodsWeight[position];
        bp.curValue += bp.goodsValue[position];
        bp.curBackpack[position] = 1;
        backTrace(position+1);
        bp.curVolume -= bp.goodsWeight[position];
        bp.curValue -= bp.goodsValue[position];
    }

    bp.curBackpack[position] = 0;
    backTrace(position+1);
}



int main(int argc, char* argv[])
{
    int volume,number;
    printf("请输入背包容量:");
    scanf("%d",&volume);
    printf("请输入物品数量:");
    scanf("%d",&number);

    initBackpack(volume, number);
    backTrace(0);

    if(bp.maxValue != 0){
        printf("背包最大价值数为:%d\n",bp.maxValue);
        printf("背包内存放的物品为:");
        for(int i=0;i < bp.number;i++){
            if(bp.lastBackpack[i] == 1){
                printf("第%d个物品;",(i+1));
            }
        }
        printf("\n");
    }else{
        printf("\n无最优解\n");
    }
    return 0;
}

声明

本文以开头博客为参考,将算法进行重新编写了下,如有异议可留言。本文为作者第一篇博文,如有错误之处,请留言指出,谢谢!

    原文作者:回溯法
    原文地址: https://blog.csdn.net/guochao6531/article/details/49402713
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞