描述
给定一个载重量为M的背包,考虑n个物品,其中第i个物品的重量 ,价值wi (1≤i≤n),要求把物品装满背包,且使背包内的物品价值最大。
有两类背包问题(根据物品是否可以分割),如果物品不可以分割,称为0—1背包问题(动态规划);如果物品可以分割,则称为背包问题(贪心算法)。
分析
有3种方法来选取物品:
(1)当作0—1背包问题,用动态规划算法,获得最优值220;
(2)当作0—1背包问题,用贪心算法,按性价比从高到底顺序选取物品,获得最优值160。由于物品不可分割,剩下的空间白白浪费。
(3)当作背包问题,用贪心算法,按性价比从高到底的顺序选取物品,获得最优值240。由于物品可以分割,剩下的空间装入物品3的一部分,而获得了更好的性能。
注意:贪心策略实现思想较简单,但是对于某些问题可能求解出来的并不是最优解
代码
仅求最优值
#include<iostream>
#include<algorithm>
using namespace std;
struct bag
{
int w;
int v;
double c;
} a[1001];
bool cmp(bag a,bag b)
{
return a.c >= b.c;
}
double knapsack(int n, bag a[], double c)
{
double cleft = c;
int i = 0;
double b = 0;
while(i<n && a[i].w<cleft)
{
cleft -= a[i].w;
b += a[i].v;
i++;
}
if (i<n)
b += 1.0*a[i].v*cleft/a[i].w;
return b;
}
int main()
{
int c;
int n;
int i;
while(cin>>c>>n)
&& c)
{
for(i=0; i<n; i++)
{
cin>>a[i].w>>a[i].v);
a[i].c = 1.0*a[i].v/a[i].w;
}
sort(a, a+n, cmp);
cout<<knapsack(n,a,c);
}
return 0;
}
求解向量
#include<iostream>
#include<algorithm>
using namespace std;
struct bag
{
int w;
int v;
double x;
int index;
double c;
} a[1001];
bool cmp(bag a,bag b)
{
if(a.c >b.c)
return true;
return false;
}
double knapsack(int n, bag a[], double c)
{
double cleft = c;
int i = 0;
double b = 0;
while(i<n && a[i].w<=cleft)
{
cleft -= a[i].w;
b += a[i].v;
a[a[i].index].x = 1.0;
i++;
}
if (i<n)
{
a[a[i].index].x = 1.0*cleft/a[i].w;
b += a[a[i].index].x*a[i].v;
}
return b;
}
int main()
{
int c;
int n;
int i;
while(cin>>c>>n && c)
{
for(i=0; i<n; i++)
{
cin>>a[i].w>>a[i].v;
a[i].c = 1.0*a[i].v/a[i].w;
a[i].x = 0;
a[i].index = i;
}
sort(a, a+n, cmp);
knapsack(n,a,c);
cout<<knapsack(n,a,c);
for(i=0; i<n; i++)
if (a[i].x==0)
cout<<"0 ";
else if (a[i].x==1)
cout<<"1 ";
else
cout<< a[i].x;
cout<<endl;
}
return 0;
}