贪心算法-背包问题

时间:2022-08-03 04:22:59

背包问题

**已知容量为M的背包和n件物品。第i件物品的重量为wi,价值是pi,且将物品i的一部分xi放进背包即可以获得pi*xi的价值。那么,怎么装包才能获得最大价值?**

若采用贪心算法,有如下几种方案可选:
  • 1、每次选择最轻的物品;
  • 2、每次选择最大价值的物品;
  • 3、每次选择性价比最大的物品,即pi/wi最大。

    方案1只考虑多装物品,但由于性价比不一定高,故总价值可能不是最大;方案2忽略了物品的重量,每次选择的价值虽大,但装的物品比较少;事实证明方案3能够达到总价值最大。

    C语言实现

// 贪心算法-背包问题.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <algorithm>
using namespace std;
#define N 3
typedef struct 
{
    int w;//重量
    int v;//价值
    double c; //性价比
}bag;
bool cmp(bag a, bag b)
{
    return a.c > b.c;
}
double GreedyKnapsack(bag a[], int n, double weight)
{ //返回最大价值
    double c_left = weight;  //背包的剩余容量
    int i = 0;
    double b = 0; //获得的价值
    while (i < n&&a[i].w < c_left)
    { //能够放下整个的物品时
        c_left = c_left - a[i].w;
        b = b + a[i].v;
        ++i;
    }
    if (i < n)
    {//只能放下物品的一部分时
        b = b + a[i].v*(c_left / a[i].w);
    }
    return b;
}
int main()
{
    int sum_weight;
    double value;  // 书包所能容纳的最大价值
    printf("请输入书包的负重:");
    scanf_s("%d", &sum_weight);

    bag bags[N];
    printf("请依次输入%d种物品的重量和价值:\n",N);
    for (int i = 0; i < N; i++)
    {
        scanf_s("%d", &bags[i].w);
        scanf_s("%d", &bags[i].v);
        bags[i].c = (bags[i].v*1.0) / bags[i].w;
    }
    //测试用例 
    //bags[0].w = 4;
    //bags[0].v = 2;
    //bags[0].c = 0.5;

    //bags[1].w = 2;
    //bags[1].v = 6;
    //bags[1].c = 3.0;

    //bags[2].w = 4;
    //bags[2].v = 4;
    //bags[2].c = 1.0;
    sort(bags, bags + N, cmp);
    value=GreedyKnapsack(bags, N, sum_weight);
    printf("该书包所能容纳的最大价值是:%.2f\n", value);
    return 0;
}