部分背包问题(贪心算法)

部分背包问题是基于贪心法的基本思想。

何谓贪心法,只要你够贪心,就能领略贪心算法之精髓。

部分背包问题和0/1背包问题的区别就是:部分背包问题中的单个物品,可以取一部分装入背包。而0/1背包问题则是要么全部拿走,要么一无所有(这里引用了LOL卡牌大师的台词)。 那么作为一个so greed的你,肯定应该知道按照什么顺序拿物品的把。没错,看着值钱的先抢! 这里所说的值钱,指的是单位重量所产生的价值越大(即value/weight的比值越大)。那么问题很简单咯~,把"值钱"的东西排在前面,每次拿抢的时候,问问看背包君够不够承受得住,承受的了,就全部抢过来。承受不住,那么只能按照所能承受的重量,取物品的一部分了。当然价值也得按照比例来哦~
 

/************************************************************************
*
* 文件名:背包问题.cpp
*
* 文件描述:要求用贪心算法去解决背包问题,这种类型的背包问题比0-1背包问题好解决,一般只需要
*           用价值除以重量然后按照从大到小的顺序依次装入就行了直至背包装满。
*
* 创建人:  fdk

* 时  间:  2018-11-08
*
* 版本号:1.0
*
* 修改记录:
*
************************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#include<limits.h>
#define max 100
using namespace std;

/*排序函数,将物品按照从大到小排序(价值/重量)*/
void swap (float ave[], int s[], int n)
{
    int i, j;
    for (i = 0; i < n; i++)
    {
        for (j = i+1; j < n; j++)
        {
            /*如果前面的值小于后面的值则调换位置*/
            if (ave[s[i]] <= ave[s[j]])
            {
                /*注意这里互换的是下标并不是真正的值,因为后面还要用到重量*/
                int temp = s[i];
                s[i] = s[j];
                s[j] = temp;
            }
        }
    }
}

/*求背包的最大价值*/
void bag (float w[], float p[], int s[], float volume, int n)
{
    int i;
    float totalV = 0; //总价值
    for (i = 0; i < n; i++)
    {
        /*如果当前的容量能装下i物品,则全部装入*/
        if (volume >= w[s[i]])
        {
            volume -= w[s[i]]; //背包的容量减去装入的重量
            totalV += p[s[i]]; //将当前背包的价值加上装入的物品的价值
            cout << "重量为" << w[s[i]] << ",价值为" << p[s[i]] << "的物品被全部拿走" << endl;
        }
        else
        {
            /*如果不能全部装入则装入部分直至全部装满*/
            totalV += volume/ w[s[i]] * p[s[i]]; //相应的价值按照相应的比例乘以重量
            cout << "重量为" << w[s[i]] << ",价值为" << p[s[i]] << "的物品拿走" << volume / w[s[i]] << endl;
            volume = 0;
            break;
        }
    }
    cout << "能装满的最大价值为:" << totalV << endl;
}
int main()
{
    int s[20], i;
    float w[20], p[20]; //w为重量,p为价值

    cout << "请输入最大重量:" << endl;
    float volume; //最大重量
    cin >> volume;

    cout << "请输入商品的种类数量:" << endl;
    int n; //商品种类数量
    cin >> n;

    cout << "请输入各个商品的重量和价值:" << endl;
    for (i = 0; i < n; i++)
    {
        cin >> w[i] >> p[i];
    }

    float ave[20]; //ave为单位重量上的价值
    for (i = 0; i < n; i++)
    {
        ave[i] = p[i] / w[i]; //重量除以价值
    }

    for (i = 0; i < n; i++)
    {
        /*下标函数*/
        s[i] = i;
    }

    swap(ave, s, n);
    bag(w, p, s, volume, n);
    return 0;
}

测试用例:


30 6

10  12
9    9
11  7
12  9
7    8
3    4

输出结果:

参考博客:https://blog.csdn.net/mll1208596630/article/details/50358286 

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值