0-1背包问题(回溯算法)

问题描述

给定n种物品和一背包。物品i的重量为wi,其价值为vi, 背包容量为c。问应如何选择装入背包中的物品,使得背入背包的物品的总价值最大?

完整代码

#include "stdafx.h"
int n;//物品的个数
int c;//背包的容量
int bestp;//最大价值(最优值)
int p[20],w[20];//存每个物品的价值和重量
int x[20],bestx[20];

int Bound(int i, int cp,int cw){//限界函数
	int cleft=c-cw;//剩余容量
	int b=cp;
	//以物品单位重量价值递减次序装入物品
	while(i<=n && w[i]<cleft)
	{	
		cleft-=w[i];
		b+=p[i];
		i++;
	}
	//装满背包
	if(i<=n){
        b+=p[i]*cleft/w[i];
     	return b;
	} 
}

void Backtrack(int i,int cp,int cw){   
	if(i>n){//回溯结束    
		if(cp>bestp){//cp当前包内物品价值     
	        bestp=cp;
            for(i=1;i<=n;i++){
               bestx[i]=x[i];
			}
        }
	   return;
    }
    if(cw+w[i]<=c){ //进入左子树
		x[i]=1; 
	    cw+=w[i];  
		cp+=p[i];
        Backtrack(i+1,cp,cw);
        cw-=w[i];
		cp-=p[i];
    }
    if(Bound(i+1,cp,cw)>bestp){ //进入右子树 
		x[i]=0;
		Backtrack(i+1,cp,cw);
	}
}


int main(int argc, char* argv[])
{
	int i;
    printf("请输入物品的数量:\n");
    scanf("%d",&n);
    printf("请输入每个物品的重量和价值:\n");
    for(i=1;i<=n;i++) {    
       scanf("%d%d",&w[i],&p[i]);
    }
    printf("请输入背包的容量:\n");
    scanf("%d",&c);
    Backtrack(1,0,0);
    printf("最大价值为:\n%d",bestp);
    printf("\n最优解为:\n");
    for(i=1;i<=n;i++)
    {
         printf("%d ",bestx[i]);
    }
	printf("\n");
	return 0;
}

测试

**测试过程:**运行程序,根据提示输入物品的数量,每个物品的重量和价值以及背包的容量,回车后系统显示最大的价值即最优值和最优解。
在这里插入图片描述

问题讨论

**讨论时间复杂度:**在最坏的情况下,所搜索的结果是一个满二叉树,此时相当于采用的就是穷举法,时间复杂度为在这里插入图片描述,而每次决定是否要讲n个物品放入背包都要进行比较,这一步的时间复杂度为n,所以最坏情况下时间复杂度为在这里插入图片描述

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LongTermism

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值