贪心法——0-1背包问题与背包问题
问题:
0-1背包问题:给定n个物品和一个背包。物品i的重量为wi,其价值为vi,背包的容量为c。问应如何选择装入背包中的物品,使得装入背包中的物品总价值最大?
说明:同一物品不能装入多次,也不能装入物品的一部分。
背包问题:与0-1背包问题类似,所不同的是在选择物品i装入背包时,可以选择物品的一部分,而不一定要全部装入背包。
问题分析:
对于背包问题而言,执行尽量装入最大单位重量价值的贪心选择即可,其正确性证明略。对于0-1背包问题,则不可以用贪心算法,因为背包有可能留下空隙,使得最后的整体单位重量价值减小,假如最后没留下空隙,也不行,有可能选了贪心选择之后剩下的空间只能让你选一个非常不好的解,最终导致解不是最优的。
代码:
#include<bits/stdc++.h>
using namespace std;
struct obj{
float w;
float v;
float vw;
obj(float _vw,float _w){
w = _w;
vw = _vw;
v = w*vw;
}
};
bool cmp(obj x,obj y){
return x.vw >= y.vw;
}
// 贪心法求解背包问题
// 输入:物品数量n,背包容量c,按照单位重量排好的物品序列a
void Knapsack(int n, float c, obj a[]) {
float sumv = 0;
for(int i = 0;i < n;i++){
if(c > a[i].w){
c -= a[i].w;
sumv += a[i].v;
cout<<i+1<<": "<<a[i].w<<endl;
}else{
cout<<i+1<<": "<<c<<endl;
sumv += c*a[i].vw;
c = 0;
}
}
cout<<sumv<<endl;
}
int main(){
int n = 3;
float c = 15;
obj a[3] = {{5,10},{2,8},{3,9}};
sort(a,a+3,cmp);
Knapsack(n, c, a);
}
复杂度:
时间复杂度:排序O(nlogn) + 贪心复杂度O(n)
空间复杂度:O(n)