贪心法——0-1背包问题与背包问题

贪心法——0-1背包问题与背包问题

问题:

0-1背包问题:给定n个物品和一个背包。物品i的重量为wi,其价值为vi,背包的容量为c。问应如何选择装入背包中的物品,使得装入背包中的物品总价值最大?
说明:同一物品不能装入多次,也不能装入物品的一部分。

背包问题:与0-1背包问题类似,所不同的是在选择物品i装入背包时,可以选择物品的一部分,而不一定要全部装入背包。

问题分析:

对于背包问题而言,执行尽量装入最大单位重量价值的贪心选择即可,其正确性证明略。对于0-1背包问题,则不可以用贪心算法,因为背包有可能留下空隙,使得最后的整体单位重量价值减小,假如最后没留下空隙,也不行,有可能选了贪心选择之后剩下的空间只能让你选一个非常不好的解,最终导致解不是最优的。

代码:

#include<bits/stdc++.h>

using namespace std;

struct obj{
    float w;
    float v;
    float vw;
    obj(float _vw,float _w){
        w = _w;
        vw = _vw;
        v = w*vw;
    }
};

bool cmp(obj x,obj y){
    return x.vw >= y.vw;
}

// 贪心法求解背包问题
// 输入:物品数量n,背包容量c,按照单位重量排好的物品序列a
void Knapsack(int n, float c, obj a[]) {
    float sumv = 0;
    for(int i = 0;i < n;i++){
        if(c > a[i].w){
            c -= a[i].w;
            sumv += a[i].v;
            cout<<i+1<<": "<<a[i].w<<endl;
        }else{
            cout<<i+1<<": "<<c<<endl;
            sumv += c*a[i].vw;
            c = 0;
        }
    }
    cout<<sumv<<endl;
}


int main(){
    int n = 3;
    float c = 15;
    obj a[3] = {{5,10},{2,8},{3,9}};
    sort(a,a+3,cmp);
    Knapsack(n, c, a);
}

复杂度:

时间复杂度:排序O(nlogn) + 贪心复杂度O(n)

空间复杂度:O(n)

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回溯法是解决0-1背包问题的一种常用方法。该问题是指在给定n种物品和一个容量为C的背包的情况下,如何选择装入背包的物品,使得装入背包中物品的总价值最大。回溯法的基本思路是搜索所有可能的解,并在搜索过程中剪枝,以达到减少搜索次数的目的。具体实现可以参考引用中的递归函数rKnap。 在回溯法中,我们首先将物品按照单位重量的价值递减排序,然后从第一个物品开始搜索。对于每个物品,我们有两种选择:将其放入背包或不放入背包。如果将其放入背包,我们需要检查当前背包容量是否足够,如果足够,则将其放入背包,并更新当前背包的重量和价值。然后递归搜索下一个物品。如果不将其放入背包,则直接递归搜索下一个物品。在搜索过程中,我们需要记录当前背包的重量和价值,以及当前最优解的最大价值。如果当前背包的价值已经超过当前最优解的最大价值,则可以剪枝,不再继续搜索。 C++代码实现可以参考以下范例: <<范例: #include <iostream> #include <algorithm> using namespace std; const int MAXN = 100; int n, c; int w[MAXN], v[MAXN]; int bestv = 0, curv = 0, curw = 0; void backtrack(int i) { if (i > n) { bestv = max(bestv, curv); return; } if (curw + w[i] <= c) { curw += w[i]; curv += v[i]; backtrack(i + 1); curw -= w[i]; curv -= v[i]; } if (curv + v[i] * (c - curw) > bestv) { backtrack(i + 1); } } int main() { cin >> n >> c; for (int i = 1; i <= n; i++) { cin >> w[i] >> v[i]; } sort(w + 1, w + n + 1); sort(v + 1, v + n + 1); backtrack(1); cout << bestv << endl; return 0; } >>

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值