背包问题(贪心算法)(代码片段)

outthinker outthinker     2022-10-29     574

关键词:

注意:这是背包问题,而不是0-1背包问题,背包问题可以用贪心算法进行求解,但0-1无法用贪心算法求解,需要用动态规划算法求解;

首先对贪心算法做一下总结,以及它与动态规划算法的区别:

贪心算法两个最重要的性质:

(1)贪心选择性质;

(2)最优子结构性质;

其中,贪心选择性质:自顶向下进行决策,每次做出的决策都是局部最优解,且每次做出决策后问题规模都变小了;最优子结构性质:即问题的最优解结构中包含子问题的最优解;

 

动态规划算法的两个最重要的性质:

(1)重叠子问题性质;

(2)最优子结构性质;

其中最优解子结构性质和贪心算法相似,唯一不同的是重叠子问题性质,因为动态规划算法是自底向上的算法,它需要首先将原始问题分解为若干个相互有联系的子问题,在计算的时候有的子问题可能会被计算很多次,所以动态规划算法会将这些子问题的解存在一个表格中,使得最终对于这些子问题只需要求解一次(可以使原来需要再指数时间内解决的问题可以在多项式问题中得到解决)

背包问题求解代码如下:

(其中使用的排序算法基于合并排序算法)

#ifndef MERGE_SORT_H
#define MERGE_SORT_H

template <class Type>
void MergeSort(Type a[], int n);

#endif

 

//merge_sort.template实现部分
#include "merge_sort.h"

template <class Type>
void MergeSort(Type *a , Type *v, int n)  //a是重量,v是价值

    Type *b = new Type[n];
    int s = 1;
    while (s < n)
    
        MergePass(a, b, v , s, n);  //合并到数组b
        s += s;
        MergePass(b, a, v , s, n);  //合并到数组a
        s += s;
    
    delete b;


template <class Type>
void MergePass(Type *x, Type *y, Type *v, int s, int n)

    int i = 0;
    while (i <= n - s * 2)
    
        Merge(x, y ,v , i, i + s - 1, i + 2 * s - 1);  //合并大小为s的相邻两段子数组
        i += s * 2;
    
    if (i + s < n)  //剩下的元素少于2s
        Merge(x, y, v, i, i + s - 1, n - 1);
    else for (int j = i; j <= n - 1; j++)
        y[j] = x[j];


template <class Type>
void Merge(Type *c, Type *d, Type *v , int l, int m, int r)  //合并c[l:m]和c[m+1:r]到d[l:r],其中c[l:m]和c[m+1:r]都是已经经过升序排好的数组

    int i = l, j = m + 1, k = l;
    while ((i <= m) && (j <= r))
    
        if ((v[i] / c[i]) >= (v[j] / c[j]))  //这里使用降序排序
            d[k++] = c[i++];
        else
            d[k++] = c[j++];
    
    if (i > m)
        for (int q = j; q <= r; q++)
            d[k++] = c[q];
    else for (int q = i; q <= m; q++)
        d[k++] = c[q];
//背包问题,使用贪心算法进行求解
//======================================================
#include <iostream>
#include "merge_sort.cpp"

using namespace std;


void init_data(float *v, float *w, float *x, int n)  //初始化数据

    cout << "请输入每类物体的价值:" << endl;
    for (int i = 0; i < n; i++)
    
        cin >> v[i];
    
    cout << "请输入每类物体的重量: " << endl;
    for (int i = 0; i < n; i++)
    
        cin >> w[i];
    
    for (int i = 0; i < n; i++)
        x[i] = 0;


void Knapsack(int n, float M, float *v, float *w, float *x)
//n是物体的种类数,M是背包容量,v是每类物体的价值,w是每类物体的重量,x是每类物体装入的份额,属于[0,1]

    int i = 0;
    float c = M;

    MergeSort(w , v , n);  //v[i]/w[i]是每一类物体的单位重量价值,然后对它们进行降序排序

    for (i = 0; i < n; i++)
    
        if (w[i] > c)
            break;
        x[i] = 1;
        c -= w[i];
    
    if (i < n)
        x[i] = c / w[i];


int main(void)

    float M = 0.0;  //背包容量
    cout << "请输入背包容量:  ";
    cin >> M;
    int n = 0;  //物体数量
    cout << "\n请输入物体数量 n :  ";
    cin >> n;
    float *v = new float[n];
    float *w = new float[n];
    float *x = new float[n];

    init_data(v, w, x, n);  //初始化数据
    Knapsack(n, M, v, w, x);

    cout << "排好序的w[i]:  " << endl;
    for (int i = 0; i < n; i++)
    
        cout << w[i] << "  ";
    
    cout << "\n\n输出最后的决策x[i] : " << endl;
    for (int i = 0; i < n; i++)
    
        cout << x[i] << "  ";
    

    /*MergeSort(w, v, n);
    cout << "输出排好序的w[i] : " << endl;
    for (int i = 0; i < n; i++)
    
        cout << w[i] << "  ";

    */
    system("pause");
    delete v , w , x;
    return 0;

 

背包问题(贪心算法)(代码片段)

  贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。  贪心算法还是比较好理解的一个算法,以前我也... 查看详情

c_cpp【贪心算法】背包问题【4.2】(代码片段)

查看详情

贪心算法之背包问题(代码片段)

问题描述:给定n种物品,1个背包,背包容量为c,每个物品i的价值为vi,重量为wi,如何选择装入物品能使背包的总价值最大?注意:与0-1背包问题不同,在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背... 查看详情

0-1背包问题贪心算法动态规划(代码片段)

1、0-1背包问题       0-1背包问题:有一个贼在偷窃一家商店时,发现有n件物品,第i件物品价值vi元,重wi磅,此处vi与wi都是整数。他希望带走的东西越值钱越好,但他的背包中至多只能装下W磅的东西&... 查看详情

背包问题基于matlab带权重的贪心萤火虫算法求解0-1背包问题含matlab源码045期(代码片段)

一、获取代码方式1引言背包问题(KnapsackProblem,KP)是NP-Complete问题,也是经典的组合优化问题,背包问题不仅具有重要的理论意义,同时还有非常重要和广泛的实际应用,如决策投资、资源分配、货物装载与预算控制等。0-1背包问题是最... 查看详情

漫画:什么是“贪心算法”?如何求解“部分背包问题”?(代码片段)

...——————........我们回到刚才的题目当中,假设背包的容量是10,有5个商品可供 查看详情

数据结构与算法笔记(十七)——贪心算法及经典案例(找零问题背包问题拼接最大数字问题活动选择问题)(代码片段)

一、贪心算法贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。贪心算法并不保证会得到最优... 查看详情

数据结构与算法笔记(十七)——贪心算法及经典案例(找零问题背包问题拼接最大数字问题活动选择问题)(代码片段)

一、贪心算法贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。贪心算法并不保证会得到最优... 查看详情

算法导论——贪心算法(代码片段)

...。        典型的例子如分数背包问题:背包容量为50kg,有三个商品分别是重60元/10kg、100元/20kg、120元/30kg,商 查看详情

[知识点]2.3贪心算法(代码片段)

...//www.cnblogs.com/jinkun113/p/12528423.html)子目录列表1、贪心2、背包问题3、正确性证明 2.3贪心算法1、什么是贪心顾名思义,贪心算法是指以一种贪婪的思维去计算每一个步骤并做出决策的过程,它往往是“目光短浅”的,... 查看详情

算法学习——贪心算法之可拆背包(代码片段)

算法描述已知道n种物品和一个可容纳c重量的背包,第i种物品的重量为wi,价值为pi,装包的时候可以把物品拆开(即可只装每种物品的一部分),设计如何装包,使装包所得整体的价值最高?算法思路首先,我们要知道,n种物... 查看详情

贪心算法(代码片段)

...我们先看一个例子。假设我们有一个可以容纳100kg物品的背包,可以装各种物品。我们有以下5种豆子,每种豆子的总量和总价值都各不相同。为了让背包中所装物品的总价值最大,我们如何选择在背包中装哪些豆子?每种豆子又... 查看详情

可拆背包问题(贪心)(代码片段)

问题描述:已知n种物品和一个可容纳c重量的背包,物品i的重量为wi,产生的效益为pi。装包时物品可以拆,即只装物品的一部分或者全部或者不装。最大的重量不能超过c。求整体效益最大。 算法思想:首先先求单位重量效... 查看详情

什么是算法?从枚举到贪心再到启发式(上)(代码片段)

...假定屏幕前的你只有大一刚学完谭浩强红本本的水平。从背包问题说起所谓算法嘛,肯定是要用来求解问题的。因此我们接下来的展开都需要围绕一个问题展开,那么我就用最简单的0-1背包问题(1-0knapsackproblem)来给大家讲讲吧... 查看详情

背包问题(代码片段)

背包问题贪心算法一问题描述二问题分析**三代码实现packageknapsnap;importjava.io.BufferedWriter;importjava.io.FileWriter;importjava.io.IOException;importjava.util.Arrays;importjava.util.Comparator;publicclassbinpublicstaticvo 查看详情

部分背包问题-贪心策略(代码片段)

部分背包问题有n个物体,第i个物体的重量为wi,价值为vi,在总重量不超过c的情况,使得总价值最高,求最大总价值,每个物体都可以之取走一部分,价值和重量按照比例算。输入:5123453431410输出... 查看详情

背包问题(贪心策略)(代码片段)

原创给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?物品时可以拆分的,比如可以将物品的三分之一放入背包。使用优先放入【价值/重量... 查看详情

使用贪心python算法解决背包问题

】使用贪心python算法解决背包问题【英文标题】:Solvingknapsackproblemusingagreedypythonalgorithm【发布时间】:2018-10-0520:20:25【问题描述】:我正在尝试使用Python解决背包问题,实现贪心算法。我回来的结果对我来说毫无意义。背包:... 查看详情