通过贪心算法来解决背包问题

通过贪心算法来解决背包问题

  给定一个载重量为M的背包,考虑n个物品,其中第i个物品的重量 ,价值wi (1≤i≤n),要求把物品装满背包,且使背包内的物品价值最大。 有两类背包问题(根据物品是否可以分割),如果物品不可以分割,称为0—1背包问题(动态规划);如果物品可以分割,则称为背包问题(贪心算法)。

  假设xi是物品i装入背包的部分(0≤xi≤1),当xi=0时表示物品i没有被装入背包;当xi=1时表示物品i被全部装入背包。

  有3种方法来选取物品:

(1)当作0—1背包问题,用动态规划算法,获得最优值220;

(2)当作0—1背包问题,用贪心算法,按性价比从高到底顺序选取物品,获得最优值160。由于物品不可分割,剩下的空间白白浪费。

(3)当作背包问题,用贪心算法,按性价比从高到底的顺序选取物品,获得最优值240。由于物品可以分割,剩下的空间装入物品3的一部分,而获得了更好的性能。

注意:

1.在动态规划算法中,每步的选择往往依赖于相关子问题的解,因而只有在解出相关子问题后,才能做出选择。

2.在贪心算法中,仅在当前做出最好的选择,即局部最优选择,然后再去解出这个选择后的相应子问题。

  我在这里写的是通过贪心算法来解决背包问题。

\sum_{i=1}^{n}w_{i}x_{i}=M         s.t.max\sum_{i=1}^{n}p_{i}x_{i}      其中,0≤xi≤1。

  

n123
重量102030
价值60100120
性价比654
#include<bits/stdc++.h>
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) //背包仍能装下物品i
    {
        cleft-=a[i].w;
        b+=a[i].v;
        i++;
    }
    if(i<n)b+=1.0*a[i].v*cleft/a[i].w;//物品i不能被完整装下,用物品i装满背包的剩余空间
    return b;  //返回最高价值
}
int main()
{
    for(int i=0;i<=2;i++)//10 60 6   20 100 5   30 120 4
    {
        cin>>a[i].w>>a[i].v>>a[i].c;
    }
    double c=knapsack(3,a,50);
    cout<<c;
}

  如果要获得解向量,则需要在数据结构中加入物品编号与装入量。

#include<bits/stdc++.h>
using namespace std;
struct bag{
int w;    //物品的重量
int v;    //物品的价值
double x;     //装入背包的量 
int index;   //物品编号
double c;   //性价比
}a[1001];    //存放物品的数组
bool cmp(bag a,bag b)   //按性价比降序排序
{
    return a.c>b.c;
}
knapsack(int n,bag a[],double c)//物品数量    按物品的性价比降序排序后的数组    背包的容量
{
    double cleft=c;   //背包剩余容量
    int i=0;
    double b=0;
    while(i<n&&a[i].w<cleft)   //背包仍能装下物品i
    {
        cleft-=a[i].w;
        b+=a[i].v;
        a[a[i].index].x=1.0;
        i++;
    }
    if(i<n)//物品i不能被完整装下,用物品i装满背包的剩余空间
    {
        a[a[i].index].x=1.0*cleft/a[i].w;
        b+=a[a[i].index].x*a[i].v;
    }
    cout<<b<<endl;  //输出最大值和解向量
    for(int i=0;i<=2;i++)
    cout<<a[i].x<<"  ";
}
int main()
{
    for(int i=0;i<=2;i++)//10 60 6 1  20 100 5 2  30 120 4 3
    {
        cin>>a[i].w>>a[i].v>>a[i].c>>a[i].index;
    }
    knapsack(3,a,50);
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值