背包问题贪心法可解的证明
0.问题描述
给定一个背包,容积为c,给定n个物品{1,2……n},以及每个物品的价值vi ,体积wi,每个物品不一定要全部放入,可以是物品的一部分。求可以放入背包的物品最大价值。
1.问题分析
求一个最优的物品的集合E., 即求max{∑vj} (j∈E, ∑wj≤c)
①最优子结构性质: 原问题的物品集合为S,设原问题的一个最优解E(选择的物品组成的集合),E集合中一个物品是A,那么E-{A}是S-{A}在容量为C - V(A)下的最优解
证明:
①假设规模为n的问题有最优解E,E-{A}的不是S-{A}规模中最优的解:即存在Value(E') > Value(E),
那么Value(S) = Value(E) + Value(A) < Value(E') + Value(A) 因此S不是原问题的最优解,与假设矛盾。
②贪心选择性质:
特点:物品可以加入一部分。
分析:可以一份一份地考虑,这个时候我们欲先将单位重量价值最大地装上。
证明:
①假设原问题有一个最优E,它不是按照贪心选择开始的。E中放入的第一个单位重量的物品是A, 由假设可知A不是单位重量价值最大的。
② 假设在S-E中有一个单位重量的物品B,, 令 ∴ ,因为E是一个最优解,因此S-E中不存在这样的B,假设不成立。
③假设E中另外一个单位重量的物品C,,交换A,B的放入顺序,得到一个方案, 因为中的物品和E中的一致,只是放入的顺序不同,所以是原问题的一个最优解。
③通过每一步的贪心可以得到最优解。
①|E| = 1时,放入的第一单位物品时单位重量价值最大的,由贪心选择性质可知,成立。
②假设当|E|=k时成立。即放入的第k单位物品是剩下物品中单位重量价值最大的。
③当|E|=k+1时:
- 由贪心选择性质,剩下物品中第一个放入单位重量价值最大的物品可以得到S - {1,2……k} 最优解。
- 由最优子结构性质,E - {1,2,……k} 是 S - {1,2……k}的最优解。因此放入第k+1个物品时,选择剩下物品中单位重量价值最大的,可以得到最优解。
综上,假设成立,通过每一步的贪心可以得到整体最优解。
3.算法流程:
代码:
struct PerW{
double perw;
int w;
int v;
};
bool cmp(PerW p1, PerW p2){
return p1.perw>p2.perw;
}
int GreedyPack(int n,int c,PerW* per){
PerW p;
int i,result=0;
sort(per,per+n,cmp);
i=0;
while(c>0&&i<n){
p=per[i++];
if(c>p.w) result+=p.v;
else{
result+=(p.perw*c);break;
}
c-=p.w;
}
return result;
}