回溯法解决01背包问题

1.装入背包中物品重量和恰好为W

//采用进一步剪枝求解0/1背包问题的算法
#include <iostream.h>
//#include <string.h>
#define MAXN 20					//最多物品数
//问题表示
int n=4;						//4种物品
int W=6;						//限制重量为6
int w[]={5,3,2,1};			//存放4个物品重量
int v[]={4,4,3,1};			//存放4个物品价值
//求解结果表示
int x[MAXN];					//存放最终解
int maxv; 						//存放最优解的总价值
void dfs(int i,int tw,int tv,int rw,int op[]) //求解0/1背包问题
{
	int j;
	if (i>n)					//找到一个叶子结点
	{	if (tw==W && tv>maxv) 	//找到一个满足条件的更优解,保存它
		{	maxv=tv;
			for (j=1;j<=n;j++)	//复制最优解
				x[j]=op[j];
		}
	}
	else						//尚未找完所有物品
	{	if (tw+w[i]<=W)  		//左孩子结点剪枝:满足条件时才放入第i个物品
		{
			op[i]=1;			//选取第i个物品
			dfs(i+1,tw+w[i],tv+v[i],rw-w[i],op);
		}
		    if (tw+rw>W)			//右孩子结点剪枝
				op[i]=0;				//不选取第i个物品,回溯
		
			dfs(i+1,tw,tv,rw-w[i],op);
	}
}
void dispasolution()			//输出最优解
{	int i;
	cout<<"最佳装填方案是:"<<endl;
	for (i=0;i<n;i++)
		if (x[i]==1)
		  cout<<"  选取第"<<i+1<<"个物品"<<endl;
	cout<<"总重量="<<W<<"  总价值="<<maxv<<endl;
}
void main()
{
	int i;
	int op[5];				//存放临时解
	for(i=0;i<4;i++)
		op[i]=0;
	int rw=0;
	for (i=0;i<n;i++)
		rw+=w[i];
	dfs(0,0,0,rw,op);
	dispasolution();
}

2.装入背包中物品重量和不超过W

在不超过W的情况下,V越多越好,那的东西越多越好。

#include <iostream>
using namespace std;

int n = 4;
struct pp{
	float w;
	float v;
	float p;
};


int W = 7;
int maxv = 0;
int x[4];


int bound(int i, int tw, int tv, pp A[])
{
	i++;
	while (i <= n && tw+A[i].w<=W)
	{
		tw += A[i].w;
		tv += A[i].v;
		i++;
	}
	if (i <= n)
	{
		return tv + (W - tw)*A[i].p;
	}
	else
	{
		return tv;
	}
}


void dfs(int i, int tw, int tv, int op[],pp A[])
{
	if (i > n)
	{
		maxv = tv;
		for (int i = 1; i <= n; i++)
		{
			x[i] = op[i];
		}
	}
	else
	{
		if (tw + A[i].w <= W)
		{
			op[i] = 1;
			dfs(i + 1, tw + A[i].w, tv + A[i].v, op,A);
		}
		if (bound(i, tw, tv,A) > maxv)
			{
				op[i] = 0;
				dfs(i + 1, tw, tv, op,A);
			}
	}
}

void sort_A(pp A[])
{
	for(int i=1;i<=n;i++)
		for (int j = 1; j < n; j++)
		{
			pp temp;
			if (A[j].p < A[j + 1].p)
			{
				temp = A[j + 1];
				A[j + 1] = A[j];
				A[j] = temp;
			}
		}
}

int main()
{
	pp A[5];
	A[1].w = 3;
	A[2].w = 5;
	A[3].w = 2;
	A[4].w = 1;
	A[1].v = 9;
	A[2].v = 10;
	A[3].v = 7;
	A[4].v = 4;
	for (int i = 1; i <= n; i++)
	{
		A[i].p = A[i].v / A[i].w;
	}
	sort_A(A);

	
	int op[4];
	
	dfs(1, 0, 0, op, A);
	for (int i = 1; i <= n; i++)
	{
		if (x[i])
		{
			cout << A[i].w << " ";

		}
	}
	cout << "\n最大价值为:" << maxv;
	return 0;
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值