贪心算法解背包问题

辨析:

背包问题能用贪心算法求解,但是01背包问题不能用贪心算法求解(因为01背包问题不具备贪心选择性质----通过局部最优,达不到全局最优)

        举个例子:背包容量=50;  w[]={10,20,30}  ,p[]={60,100,120}   用贪心选择(10+20)<50,p=160,但这并不是最优解,事实上(20+30)=50,p=100+120=220.才是问题的解。对于01背包,贪心采用自上而下,拆分子问题的方式为:{物品1,物品2,物品3}--->{物品2,物品3}----{物品3}............它无法保证最终能将背包装满,部分闲置的背包空间使每千克背包空间的价值降低了.
        对于该问题,我们应该采用自下而上的动态规划来求解,拆分子问题的 方式为:{物品1}-------->{物品1,物品2}------>{物品1,物品2,物品3}.在求解时,应比较,选择该物品和不选择该物品,所导致的最终方案,然后再做出最好选择,为了更快求出问题的解。动态规划还记忆了过程中产生的许多互相重叠的子问题的答案。

贪心算法采用自上而下的方式进行子问题的求解。而动态规划则采用自下而上的方式进行子问题的求解。

算法实现: 

#include<iostream>
using namespace std;
class Object {
	friend void knapsack(int, float, float*, float*);
public:
	int operator<=(Object a) const {
		return (d >= a.d);
	}
private:
	int ID;
	float d;
};

void knapsack(int n, float c, float v[], float w[]) {
	//排序:
	Object * Q = new Object[n];

	for (int i = 1; i <= n; i++) {
		Q[i - 1].ID = i;
		Q[i - 1].d = 1.0 * v[i] / w[i];
	}
	//采用简单冒泡排序
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n+1 - i; j++) {
			if (Q[j - 1].d < Q[j].d) {
				Object temp = Q[j - 1];
				Q[j - 1] = Q[j];
				Q[j] = temp;
			}
		}
//	for (int i = 1; i <= n; i++) {
//            cout<<"拍好序之后的: "<<endl;
//			cout<<"Q[i - 1].ID: "<<Q[i - 1].ID<<endl;
//			cout<<"Q[i - 1].d: "<<Q[i - 1].d<<endl;
//		}
	//注意:必须要新建v1和w1,不能用原来的v和w,否则对于Q[i - 1].ID这里Q[4].ID=1,
			//会出现 w[4]=w[1];w[4]的值就成了2,实际我们期望的w[1]应该是5
			//
	float *v1 = new float[n + 1];
	float *w1 = new float[n + 1];

	for (int i = 1; i <= n; i++) {
		v1[i] = v[Q[i - 1].ID];
		w1[i] = w[Q[i - 1].ID];
		cout<<"预处理后的装包顺序:"<<endl;
		cout<<"v1["<<i<<"]: "<<v1[i]<<"    w1["<<i<<"]: "<<w1[i]<<endl;
	}
	//排序结束:

	int i;
	float bestp=0;
	float x[n + 1];
	for (i = 1; i < n; i++) {
		x[i] = 0;
	}
	//贪心算法:
	for (i = 1; i < n; i++) {
		if (w1[i] > c)
			break;
		x[i] = 1;
		c -= w1[i];
	}
	if (i <= n)
		x[i] = c / w1[i];
	for (i = 1; i <= n; i++) {
         if(x[i]!=0){
        	 cout<<"选择放入的物品是:"<<Q[i - 1].ID<<endl;
        	 cout<<"物品的"<<x[i]<<"部分被放入了背包"<<endl;
        	 bestp+=x[i]*v[Q[i - 1].ID];
         }
	}
	cout <<"该背包问题的最大价值是:"<<bestp << endl;
}
int main() {
	float p[] = { 0, 4, 6, 3, 5, 6 };
	float w[] = { 0, 5, 4, 2, 6, 2 };
	float c = 10;
	int n = 5;
	//排好序之后的:
//    int p[]={0,6,3,6,5,4};
//    int w[]={0,2,2,4,6,5};
	knapsack(n, c, p, w);
	return 0;
}

 

  • 12
    点赞
  • 89
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值