01背包问题-蛮力-动态规划-回溯-分支限界完全代码

说明

此处代码均为本人亲自完成,复制可直接运行。因为内容较多的原因,再此不做详细介绍。本人QQ:2422380414(邮箱同号),若有不足或是疑问欢迎联系本人!

蛮力法

#include <iostream>
using namespace std;
int weight[100],value[100];		//物品重量和价值 
int Path[100],path[100];        //最终路径,与当前路径 
int W;   		//背包容量 
int N;    		//物品个数 
int Max;        //最大价值 
int V;          //当前价值 
int w;          //当前重量 

int func(int i){
	if(i>=N){
		if(V>Max&&w+value[i]<=W){
			Max=V;
			for(int i=0;i<N;i++)
			Path[i]=path[i];
		} 
		return Max;
	}
	
	//放入背包 
	w+=weight[i];
	V+=value[i];
	path[i]=1;
	func(i+1);

    //不放入背包 
	w-=weight[i];
	V-=value[i];
	path[i]=0;
	func(i+1);
	return Max;
}

int main(){
	cout<<"请输入物品个数:";
	cin>>N;
	
	cout<<"请输入背包容量:";
	cin>>W;
	
	cout<<"请依次输入每个物品的重量和价值:"<<endl;
	for(int i=0;i<N;i++)
	cin>>weight[i]>>value[i]; 
	
	cout<<"最大价值:"<<func(0)<<endl;
	cout<<"物品存放详情:"<<endl;
	for(int i=0;i<N;i++)
	cout<<Path[i]<<" "; 
	return 0; 
} 

动态规划

#include <iostream>
using namespace std;

void func(int weight[],int value[],int W,int n){
	//Dp[i][j],表示背包容量为j时,前i个物品能装入背包的最大价值。 
	int Dp[n+1][W+1];
	//初始第一列,第一行为0
	for(int i=0;i<=n;i++){
		Dp[i][0]=0;
	} 
	for(int j=0;j<=W;j++){
		Dp[0][j]=0;
	}
	//计算最大价值 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=W;j++){
			if(j<weight[i-1]){
				Dp[i][j]=Dp[i-1][j];
			}else{
				Dp[i][j]=max(Dp[i-1][j],Dp[i-1][j-weight[i-1]]+value[i-1]);
			}
		}
	}
	
	//输出选择情况 
	int path[n];
	for(int i=n,j=W;i>0;i--){
		if(Dp[i][j]>Dp[i-1][j]){
			path[i-1]=1;
			j=j-weight[i-1];
		}else{
			path[i-1]=0;
		}
	} 
	for(int i=0;i<n;i++)
	cout<<path[i]<<" ";
	cout<<endl;
	
	cout<<"最大价值为:"<<Dp[n][W]<<endl; 
}

int main(){
	int n,W;
	cout<<"请输入物品个数:";
	cin>>n;
	
	int weight[n],value[n];
	cout<<"请依次输入"<<n<<"个物品的质量和价值:"<<endl;
	for(int i=0;i<n;i++){
		cin>>weight[i]>>value[i]; 
	} 
	cout<<"请输入背包容量:";
	cin>>W; 
	
	func(weight,value,W,n);
	
	return 0;
} 

回溯

#include <iostream>
using namespace std;
int Path[100];     //Path是最终路径,path是当前路径。
void func(int weight[],int value[],int W,int n,int path[],int &Max,int V,int c,int start){
//V表示当前价值,c表示当前重量,Max表示最终得到的最大结果
	if(c<=W){
		//Max=max(Max,V);
		if(V>Max){
			Max=V;
			for(int i=0;i<n;i++)
			Path[i]=path[i];      //保存存放路径 
		}
		
		for(int i=start;i<n;i++){
			c+=weight[i];
			V+=value[i];
			path[i]=1;
			func(weight,value,W,n,path,Max,V,c,i+1);
			c-=weight[i];
			V-=value[i];
			path[i]=0;
		}
	}
} 

int main(){
	int n,W;
	cout<<"请输入物品个数:";
	cin>>n;
	
	int weight[n],value[n];
	
	int path[n]={0};//用来记录取最大值时背包所放物品 
	
	cout<<"请依次输入"<<n<<"个物品的质量和价值:"<<endl;
	for(int i=0;i<n;i++){
		cin>>weight[i]>>value[i]; 
	} 
	cout<<"请输入背包容量:";
	cin>>W; 
	int Max=0;
	func(weight,value,W,n,path,Max,0,0,0);
	cout<<"背包能装最大价值:"<<Max<<endl;
	cout<<"物品存放详情:"<<endl;
	for(int i=0;i<n;i++)
	cout<<Path[i]<<" "; 
	return 0;
} 

分支界限

#include <iostream>
#include <cmath>
using namespace std;

int Bound(int* Weights,int* Values,int n,int W,int num,int current_w,int current_v){
	int i=num+1;
	for(;i<n;i++){
		if(current_w+Weights[i]<W){
			current_v+=Values[i];
			current_w+=Weights[i];
		}else{
			current_v+=(Values[i]/Weights[i])*(W-current_w);
			current_w=W;
			return current_v;
		}
	}
	return current_v;
}

int* fun(int *Weights,int* Values,int W,int n){
	int *X=new int[n];
	int *Y=new int[n];
	int Weight=0;
	int Profit=0;
	
	int current_w=0,current_v=0;
	
	int i=0;
	while(true){
		while(i<n&&current_w+Weights[i]<=W){
			X[i]=1;
			current_v+=Values[i];
			current_w+=Weights[i];
			i++;
		}
		
		//如果由于i==n结束,说明神度搜索到最底层了
		if(i>=n){
			Weight=current_w;
			Profit=current_v;
			i=n;
			for(int i=0;i<n;i++){
				Y[i]=X[i];
			}
		} else{
			//第i个物品放不下
			X[i]=0; 
		}
		
		//如果不能获得更大的价值,舍弃当前点 ,进行回溯 
		while(Bound(Weights,Values,n,W,i,current_w,current_v)<=Profit){
			while(i!=0&&X[i]!=1){
				i--;
			}
			if(i==0){
				cout<<"最大价值:"<<Profit<<endl;
				return Y;
			}
			X[i]=0;
			current_v-=Values[i];
			current_w-=Weights[i];
		} 
		i++;
	}
}

int main(){
	int n,W;
	cout<<"输入物品个数:"; 
	cin>>n;
	cout<<"请输入背包容量:"; 
	cin>>W; 
	int Weight[n];
	int Value[n];
	int *path; 
	cout<<"请依次输入n个物品的质量和价值(V/W从大到小):"<<endl;
	for(int i=0;i<n;i++){
		cin>>Weight[i]>>Value[i]; 
	} 
	
	path=fun(Weight,Value,W,n);
	for(int i=0;i<n;i++)
	cout<<path[i]<<" ";
	
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值