问题描述
题目分析
这个问题和0-1背包问题有一定的差别,0-1背包问题的解决方法可以参加我的另一篇文章0-1背包问题
这两类问题都具有最优子结构性质。对0-1背包问题,设A是能够装入容量为c的背包的具有最大价值的物品集合,则为Aj = A-{j}是n-1个物1,2,…j-1,j+1…n可装入容量为c-wj的背包的具有最大价值的物品集合。对于背包问题,类似地,若它的一个最优解包含物品j,则从该最优解中拿出所含物品j的那部分重量w,剩余的将是n-1个原重物品1,2,…,j-1,j+1,…,n及重为wj-w的物品j中可装入容量为c-w的背包且具有最大价值的物品。
虽然这两个问题极为相似,但背包问题可以通过贪心算法解决求解,而0-1背包问题不能用贪心算法求解。用贪心算法解背包问题的基本步骤是:首先计算每种物品单位重量的夹着vi/wi;然后依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过c,则选择单位重量价值次高的物品并尽可能多地装入背包。以此策略,一直进行下去,直到背包装满为止。
代码
#include <iostream>
#include <algorithm>
using namespace std;
bool cmp(float a,float b)
{
return a > b;
}
void Sort(int n,float v[],float w[])
{
for(int i = 1;i <= n;i++)
{
v[i] = v[i] / w[i];
}
//将单位重量价值从大到小排序,并且将w也进行排序,排序的标准是单位重量价值高的排在前面
for(int i = 1;i <= n - 1;i++)
{
for(int j = 0;j <= n - i;j++)
{
swap(v[i],v[j]);
swap(w[i],w[j]);
}
}
}
void Knapsack(int n,float M,float v[],float w[],float x[])
{
Sort(n,v,w);
int i;
for(i = 1;i <= n ;i++)
x[i] = 0;
float c = M;
for(i = 1;i <= n ;i++)
{
if(w[i] > c)
break;
x[i] = 1;
c -= w[i];
}
//包内的剩余重量对于当前价值物体能装的最大数量,1表示全部加入,这里会得到一个小数
//小数表示将这一部分装入背包,例如0.5表示装一半进入背包
if(i <= n)
x[i] = c / w[i];
}
总结
时间复杂度主要取决我们使用什么样的排序算法,最好的是O(nlogn)