0/1背包问题(回溯法)

0/1背包问题。给定一载重量为W的背包及n个重量为wi、价值为vi的物体,1≤i≤n,要求重量和恰好为W具有最大的价值。

输入格式:

第一行输入背包载重量W及背包个数n,再依次输入n行,每行为背包重量wi和价值vi。

输出格式:

第一行输出装入背包内的物体编号(末尾有空格),若没有任何物品能装入,输出: No,第二行输出背包内的物体总价值。

输入样例1:

5 10
2 6
2 3
6 5
5 4
4 6

输出样例1:

1 2 3 
14

输入样例2:

2 10
11 2
13 100

输出样例2:

No
0

代码如下: 

#include <bits/stdc++.h>
using namespace std;
int C,N;//背包剩余容量,物体数量
int w[105],v[105];//物体重量,价值 
int cw=0;//当前背包重量 
int cv=0;//当前总价值 
int len=1;//当前选择长度
int best_len=1;//最佳选择长度 
int best=0;//最大价值 
int result[105];//当前物品编号
int best_result[105];//最有选择物品编号
 
//限界函数(背包的贪心算法) 
int Bound(int i)
{
	int rw=C-cw;//剩余容量
	int value=cv;//当前背包价值
	
	//假设把剩下的物品全加入背包 
	while(i<=N && w[i]<=rw)
	{
		rw-=w[i];
		value+=v[i];
		i++;
	}
	 
	//装满背包,求出若将剩余物品全部加入背包所达到的价值上限 
	if(i<=N)
	{
		value+=v[i]/w[i]*rw;//v[i]/w[i]为性价比
	} 
	
	return value; 
} 
void dfs(int k)
{
	//若递归搜索层次超过物体数量,终止 
	if(k>N && cw==C && cv>best)
	{
		best=cv; 
		best_len=len;
		for(int i=1;i<len;i++)
		{
			best_result[i]=result[i];
		} 
		return ;	
	}
	
	//如果背包容量足够装下该物品 
	if(cw+w[k]<=C)//进入左子树 
	{
		cw+=w[k];//当前背包重量 
		cv+=v[k];//当前价值增加 
		result[len]=k;
		len++; 
		k++; 
		dfs(k); 
		//回溯 
		k--;
		len--;
		result[len]=0;
		cw-=w[k];
		cv-=v[k];
	}
	
	//若不装该物品,考虑当前价值+剩余物品价值最大上限(若全部加入背包)是否比best大
	if(Bound(k+1)>best)//进入右子树 
	{
		k++;
		dfs(k);
		k--; 
	}
	
}
int main() 
{
    cin>>N>>C;
	for(int i=1;i<=N;i++)
		cin>>w[i]>>v[i];
			
	dfs(1); 
	
	if(best==0)
	{
		cout<<"No"<<endl;
		cout<<0<<endl;
	}
	else
	{
		for(int i=1;i<best_len;i++)
			cout<<best_result[i]<<" ";
		cout<<endl;
		cout<<best<<endl;
	}
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值