用回溯法求解0—1背包问题,并输出问题的最优解

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

0—1背包问题是一个子集选取问题,适合于用子集树表示0—1背包问题的解空间。在搜索解空间树是,只要其左儿子节点是一个可行结点,搜索就进入左子树,在右子树中有可能包含最优解是才进入右子树搜索。否则将右子树剪去。

int c;//背包容量

int n; //物品数

int *w;//物品重量数组

int *p;//物品价值数组

int cw;//当前重量

int cp;//当前价值

int bestp;//当前最优值

int *bestx;//当前最优解

int *x;//当前解

int Knap::Bound(int i)//计算上界

void Knap::Backtrack(int i)//回溯

int Knapsack(int p[],int w[],int c,int n) //为Knap::Backtrack初始化

【详细设计】

#include<iostream>
using namespace std;
class Knap
{
friend int Knapsack(int p[],int w[],int c,int n );
public:
       void print()
       {
       for(int m=1;m<=n;m++)
   {
    cout<<bestx[m]<<" ";
   }
   cout<<endl;
       };
private:
int Bound(int i);
void Backtrack(int i);
int c;			//背包容量
int n;			//物品数
int *w;			//物品重量数组
int *p;			//物品价值数组
int cw;			//当前重量
int cp;			//当前价值
int bestp;		//当前最优值
int *bestx;		//当前最优解
int *x;			//当前解
};
int Knap::Bound(int i)
{
	//计算上界
	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]/w[i]*cleft;
       	return b;
}
void Knap::Backtrack(int i)
{
	if(i>n)
	{
    		if(bestp<cp)
       		{
           		for(int j=1;j<=n;j++)
                  		bestx[j]=x[j];
           		bestp=cp;
       		}
       		return;
	}
	if(cw+w[i]<=c) 		//搜索左子树
	{            
      		x[i]=1;
       		cw+=w[i];
       		cp+=p[i];
       		Backtrack(i+1);
       		cw-=w[i];
       		cp-=p[i];
	}
       if(Bound(i+1)>bestp)	//搜索右子树
       {
             	x[i]=0;
              	Backtrack(i+1);
       }
}



  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个采用回溯法求解0/1背包问题的最优值和最优解的C++实现: ```cpp #include <iostream> #include <vector> using namespace std; const int MAX_N = 20; //物品数量最大值 const int MAX_W = 100; //背包容量最大值 int n, W; //物品数量、背包容量 int w[MAX_N], v[MAX_N]; //物品重量、价值 int best_v; //最优解的价值 int cur_w, cur_v; //当前解的重量、价值 vector<int> best_sol; //最优解 //回溯函数 void backtrack(int t, vector<int>& cur_sol) { if (t > n) { if (cur_v > best_v) { best_v = cur_v; best_sol = cur_sol; } return; } //不选第t个物品 cur_sol.push_back(0); backtrack(t + 1, cur_sol); cur_sol.pop_back(); //选第t个物品 if (cur_w + w[t] <= W) { cur_sol.push_back(1); cur_w += w[t]; cur_v += v[t]; backtrack(t + 1, cur_sol); cur_w -= w[t]; cur_v -= v[t]; cur_sol.pop_back(); } } int main() { cout << "请输入物品数量和背包容量:" << endl; cin >> n >> W; cout << "请输入每个物品的重量和价值:" << endl; for (int i = 1; i <= n; i++) cin >> w[i] >> v[i]; best_v = 0; cur_w = cur_v = 0; vector<int> cur_sol; backtrack(1, cur_sol); cout << "最优解的价值为:" << best_v << endl; cout << "最优解为:"; for (int i = 0; i < best_sol.size(); i++) cout << best_sol[i] << " "; cout << endl; return 0; } ``` 该程序除了采用了C++语言的特性外,与前面的C语言实现基本相同。不同之处在于,最优解使用了vector<int>类型表示,cur_sol表示当前解。在每次递归时,先尝试不选第t个物品,然后再尝试选第t个物品。如果选了第t个物品,就要更新当前解的重量和价值,并将cur_sol数组中push_back一个1,表示该物品已选中。当t>n时,说明已经枚举完了所有物品,此时如果当前解的价值比最优解的价值更大,就更新最优解的价值和best_sol数组。最后输出最优解的价值和最优解即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值