0 1背包问题

/***************************************/
/*     0/1背包问题(物体不可分割)     */
/*求装入背包的物体及其总价值           */
/***************************************/

#include<iostream>
#include<iomanip>
#define N  20    //最多物体个数
#define M  100  //最大背包载重量
using namespace std;

typedef struct{  
	float    w;			// 物体重量 
	float    p;			// 物体价值 
	float    v;			// 物体的价值重量比
} OBJECT;

int main(){
	/*函数声明*/
	void create_wuti(OBJECT T[], int t);
	void bubble_sort(OBJECT A[], int n);
	float knapsack_back(OBJECT ob[],float m,int n,bool x[]);

	OBJECT	ob[N];		//物体	
	float	m;			// 背包载重量
	bool	x[N];		// 可能的解向量 

	int n;
	cout << "请输入物体个数n(不超过20)及背包载重量m(100)分别为:";
	cin >> n >> m;

	cout << "\n-----创建物体的重量及其价值-----";
	create_wuti(ob,n);

	int v = knapsack_back(ob,m,n,x);
	cout << "\n背包中物体的最大价值为:" << v;
	cout << "\n解向量为:";
	for (int i = 0;i<n; i++)
		cout << x[i] << " ";
	cout<<endl<<endl;

	system("pause");
	return 0;
}

/*创建物体的重量及价值*/
void create_wuti(OBJECT T[], int t){
	cout << "\n请输入物体的重量:";
	for (int i = 0; i<t; i++)
		cin >> T[i].w;

	cout << "请输入物体的价值:";
	for (int i = 0; i<t; i++)
		cin >> T[i].p;
}

/*冒泡排序*/
void bubble_sort(OBJECT A[], int n){
	OBJECT t;
	for (int i = n - 1; i >0; i--){
		for (int j = 0; j < i; j++){
			if (A[j].v<A[j + 1].v){
				t = A[j];
				A[j] = A[j + 1];
				A[j + 1] = t;
			}
		}
	}
}

/*回溯法解0/1背包问题*/
float knapsack_back(OBJECT ob[ ], float m, int n,bool x[ ]){   
	float	p_est;		// 装入背包物体的估值 
	float	w_est;		// 装入背包物体的重量
	float	p_total;	// 装入背包物体的价值上界 
	float	w_cur;		// 当前装入背包的物体的总重量 
	float	p_cur;		// 当前装入背包的物体的总价值 
	bool * y = new  bool[ n+1 ]; 
	for (int j=0; j<n; j++) {		// 计算物体的价值重量比 
           ob[ j ].v = ob[ j ].p / ob[ j ].w;
           y[ j ] = false;		// 当前的解向量初始化
	}

	bubble_sort(ob,n);		// 物体按价值重量比排序

	int i,k = 0; 
	p_est=w_cur = p_cur = p_total = 0;		// 初始化
	y[n]=false; 
     
	while (k >= 0){  
		w_est = w_cur;   p_est = p_cur;
         
		for (i=k; i<n; i++){ 		// 计算最大估值  
			w_est = w_est + ob[ i ].w;
			if (w_est < m) 
                p_est = p_est + ob[ i ].p;
             else{ 
				 p_est+=((m-w_est+ob[ i ].w)/ob[ i ].w)*ob[i].p;
                 break;
			 }
		} 

        if (p_est>p_total){ 		// 估计值大于上界
              for (i=k; i<n; i++){
				  if (w_cur+ob[ i ].w <= m){ // 可装入第 i 个物体
					  w_cur = w_cur + ob[ i ].w; 
					  p_cur = p_cur + ob[ i ].p;
					  y[ i ] = true;  
				  } 
				  else{ 
					  y[ i ] =false;   break;	// 不能装入第 i 个物体
                  }
			  }
			  if ( i >= n-1){ 			// n个物体已全部装入
				  if (p_cur > p_total){
					  p_total = p_cur;   k = n;    // 刷新当前上限
					  for (i=0; i<n; i++)   
						  x[ i ] = y[ i ];        // 保存可行的解
				  }    
			  }
			  else k = i + 1;			// 继续装入其余物体
		}

		else{ 		      // 估计价值小于当前上限,即if (p_est<=p_total) 
			while ((i >= 0)&&(y[ i ] == 0))	// 沿右分支回溯
                    i--;			      // 直到左分支结点
			if (i<0)  break;		    // 已到达根结点,算法结束
			else{
				w_cur = w_cur-ob[ i ].w;	 // 修改当前值50  
				p_cur = p_cur-ob[ i ].p;
				y[ i ] =false;   
				k = i + 1;	      // 搜索右分支子树
			}
		}
	}

	delete y;        
	return p_total;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值