01背包问题之回溯法(2021/3/15)

回溯法之01背包问
手推分析

在这里插入图片描述
在这里插入图片描述

源代码
/*
名称:01背包回溯法求解
编码:高万禄
日期:2021/3/15 
*/ 
#include<iostream>
#include<cstdlib>
/*测试样例 
存储物品个数
4
购物车容量      10
依次输入物品重量W[]     2 5 4 2
依次输入物品价值V[]     6 3 5 4
W[]--V[]:       2--6    5--3    4--5    2--4
选中的物品序号为:       0       2       3
*/

using namespace std;
float nowWeight=0.0f;//当前载重
float nowPrice=0.0f;//当前装入的价值
float bestPrice=0.0f;//最优解价值
float sumWeight=0.0;//统计所有物品重量
float sumPrice=0.0;//统计所有物品总价值

float bound(float*V,int i,int N){
	float temp=0.0f;
	for(;i<N;i++){
		temp+=V[i];
	}
	return nowPrice+temp;
} 


//回溯法求解
//搜索空间,t代表现在的扩展在第t层 
void backTrack(float*W,float*V,int N,float M,int *bestChoose,int*tempChoose,int t){
	//判断是否到达了叶子节点
	if(t>=N){
		//保存当前最优解
		for(int i=0;i<N;i++){
			bestChoose[i]=tempChoose[i];
		}
		bestPrice=nowPrice;
		return;
	}
	//是否满足条件搜索左子树
	if(nowWeight+W[t]<=M){
		tempChoose[t]=1;
		nowWeight+=W[t];
		nowPrice+=V[t];
		backTrack(W,V,N,M,bestChoose,tempChoose,t+1);//探索完左子树后 
		nowWeight-=W[t];//回溯 
		nowPrice-=V[t];
	}
	//是否满足条件搜索右子树
	if(bound(V,t+1,N)>bestPrice){
		tempChoose[t]=0;
		//探索右子树
		backTrack(W,V,N,M,bestChoose,tempChoose,t+1); 
	} 
}

//返回bool数组 
int* knapsack(float*W,float*V,int N,float M){
	//求和
	for(int i=0;i<N;i++){
		sumWeight+=W[i];
		sumPrice+=V[i];
	} 
	//判断是否可以将全部物品放入购物车
	if(sumWeight<=M){
		bestPrice=sumPrice;
		cout<<"将所有物品放入购物车\n";
		return NULL;
	}
	//记录相应下标物品是否放入购物车
	int *bestChoose=(int*)malloc(sizeof(int)*N);
	//临时存储,相应下标物品是否放入购物车
	int *tempChoose=(int*)malloc(sizeof(int)*N); 
	//回溯法求解
	backTrack(W,V,N,M,bestChoose,tempChoose,0);
	free(tempChoose);
	return bestChoose;
}

//主函数 
int main(int argc,char**argv){
	int N;//存储物品的个数
	cout<<"存储物品个数\t";
	cin>>N;
	float M;
	cout<<"购物车容量\t";
	cin>>M;
	float *W=(float*)malloc(sizeof(float)*(N));
	float *V=(float*)malloc(sizeof(float)*(N));
	cout<<"依次输入物品重量W[]\t";
	for(int i=0;i<N;i++){
		cin>>W[i];
	}
	cout<<"依次输入物品价值V[]\t";
	for(int i=0;i<N;i++){
		cin>>V[i];
	}
	//输入验证
	cout<<"W[]--V[]:\t";
	for(int i=0;i<N;i++){
		cout<<W[i]<<"--"<<V[i]<<"\t";
	} 
	cout<<"\n";
	int* result=knapsack(W,V,N,M);
	free(W);free(V);
	cout<<"选中的物品序号为:\t"; 
	for(int i=0;i<N;i++){
		if(result[i]==1)
	    	cout<<i<<"\t";
	}
	cout<<"\n";
	free(result);
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

高万禄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值