基于贪心算法设计装载问题的求解;基于贪心算法设计背包问题的求解;

掌握贪心算法求解问题的思想;针对不同的问题,会利用贪心算法进行问题拆分和求解以及时间复杂度分析,并利用JAVA/C/C++等编程语言将算法转换为对应的程序上机运行(语言自选)。

理解装载问题及背包问题的贪心求解策略;对比分析与动态规划求解最优时算法异同;能够根据贪心算法,进行装载问题及背包问题最优规则选取,并编码实现。

基于贪心算法设计装载问题的求解;

针对指定容量C的船,给定n个集装箱,各集装箱重量为wi。如何将集装箱装到船上保证装的集装个数最多?

基于贪心算法设计背包问题的求解;

针对指定容量C的背包,给定n个物品,各物品具有重量wi、价值vi。如何选择物品装入背包,使得价值最大(未要求0/1性)?

④对上述算法进行时间复杂性分析,并输出程序运行时间及运行结果。

实验原理:

1、针对装载问题,如何利用贪心算法进行算法设计

分析问题:

求解的最优装载问题,要求装载的物品的数量尽可能多,而船的容量是固定的,那么优先把重量小的物品放进去,在容量固定的情况下,装的物品最多。采用重量最轻者先装的贪心选择策略,从局部最优达到全局最优,从而产生最优装载问题的最优解。

建模及约束条件

 

算法思路及策略:

先将集装箱依其重量从大到小排序,(x1,x2.......xn)是最优装载问题的一个最优解,又设k=min{i|xi=1}{ 1<=i<=n}.如果给定的最优装载问题有解,则1<=k<=n;然后选择最轻的待选物品,给出选择第一个物品是最轻的,如果第一个集装箱的重量就大于最大承重则后面的均无法装入。选完第一个物品,剩下的也是在排好序中的物品选择最轻的,这就是最优子结构。最后一个一个求出最优子结构将他们合并起来,求出装载最多的一个解。在最优子结构的综合就是装载问题的最优解。我还加入一个index记录集装箱的序号,求出加入的集装箱序号。

算法精选:

 

2、背包问题,贪心算法设计求解策略

算法思路及策略:

三种策略如下:

1、先把价值高的装进去,这样来说,能够确保背包内物品价值的有效增长,但是背包容量消耗太快,不利于总体价值的最大化。

2、先把重量小的物品装进去,这种策略能确保背包内的空间得以有效的利用,但是背包内物品的价值却不能有效增长,即增长缓慢,也不利于总体价值的最大化。

3、以上两种策略只考虑到了背包价值的增长和背包容量的利用,都不利于背包内物品价值的最大化。不妨,给每件物品赋予权重=价值/重量,并且按照物品的权重降序排序,依次将物品装入背包。

我们选第三种是最好的贪心策略,收益最高。先选取比值最大的物品。比较其重量是否小于背包容量,如果小,就放入,如果大于背包容量,就对其进行切割。循环第一步,直到背包容量等于0

求解步骤:

首先计算每种物品单位重量的价值v[i]/w[i],然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。

背包问题与0-1背包问题的区别:

具有最优子结构性质和贪心选择性质。只要是所有物品的总重量大于背包容纳量,那么背包一定能装满。这2类问题都具有最优子结构性质,极为相似,但背包问题可以用贪心算法求解,而0-1背包问题却不能用贪心算法求解。

四、实验步骤

装载问题利用贪心算法实现:

#include <iostream>

#include <algorithm>

#include <string.h>

using namespace std;

struct load {

    int index;// 集装箱的编号

    int wei;// 集装箱的重量

}box[1001];// 集装箱类型的数组,存储集装箱

bool cmp(load a, load b) {    

    if (a.wei<b.wei) return true;

    else return false;

}

int main()

{

    int c, n;

    int x[1001];// 用于记录集装箱是否被装入,数组的下标即为集装箱的编号

    printf("请输入集轮船的载重量c和集装箱的个数n:");

    while (scanf("%d %d", &c, &n)!=-1)

    {

        memset(box, 0, sizeof(box)); // 将数组box的每个值均初始化为0

        memset(x, 0, sizeof(x));// 将数组x的每个值均初始化为0

        for (int i=1; i<=n; i++)

        {

            scanf("%d", &box[i].wei);

            box[i].index = i;

        }

        stable_sort(box, box+n+1, cmp);

        if (box[1].wei>c) {

            printf("No answer!\n");

            continue;// 如果第一个集装箱的重量就大于c则后面的均无法装入

        }

        // 贪心算法的实现,重量最轻者优先装载

        int i;

        for (i=1; i<=n && box[i].wei<=c; i++)

        {

            x[box[i].index] = 1;

            c -= box[i].wei;// 每装入一个,c同时减少

        }

        printf("输出装载的集装箱数量:%d\n",i-1);

        for (i=1; i<=n; i++)

            if (x[i]) printf("输出装载集装箱的编号:%d ", i);

        printf("\n");

    }

    return 0;

}

背包问题利用贪心算法求解(JAVA)

package main;

import java.util.Arrays;

public class B {
    static class Three implements Comparable<Three>{
        Three(double w,double v){
            this.w=w;
            this.v=v;
            this.p=this.v/this.w;
        }
        double w;//
每个物的重量
        double v;//每个物的价值
        double p;//性价比
        @Override
        public int compareTo(Three o){
            return (o.p>this.p)?1:-1;
        }
    }
    public static  void main(String[] args){
        int n=5;//n
表示有n个物
        double m=150;//m是背包重量
        Three[] s=new Three[]{
                new Three(50,100),
                new Three(40,80),
                new Three(60,120),
                new Three(10,20),
                new Three(50,100)
        };
        Arrays.sort(s);
        double sum=0.0;//sum
表示贪心记录物的价值之和
        for (int i=0;i<n;i++) {//按照排好的顺序贪心
            if(m>s[i].w){//如果物的重量小于背包剩下的重量
                m-=s[i].w;
                sum+=s[i].v;
            }else{
                sum+=m*s[i].p;//
部分装入
                break;
            }
        }
        System.out.println("
最大价值:"+sum);
    }
}

五、记录与处理(实验数据、误差分析、结果分析)

装载问题:c=200,n=4

C=100,n=5

 

背包问题:

1.n=5,m=150

 

2.n=4,m=200

 

六、思考与总结

主要撰写:

贪心算法理解:

将问题从初始解开始,在每一个阶段都用贪心策略求出当前子集最优策略,逐步靠近目标,尽可能快地求得更好的解。当达到算法中不能再继续前进时,算法终止。贪心算法都是要当前最有利的选择,不考虑未来,而且不能回溯,根据贪心策略来逐步构造问题的解。如果所选的贪心策略不同,则得到的贪心算法就不同。还有就是局部解不一定是最优解,即便不是最优解,也一定是最优解的近似解。贪心法的解题步骤:分解,解决,合并。求解中两个重要性质是最优子结构性质和贪心选择性质。

装载问题理解

先将集装箱依其重量从大到小排序,然后选择最轻的待选物品,给出选择第一个物品是最轻的,如果第一个集装箱的重量就大于最大承重则后面的均无法装入。接一下也是依次选当前最轻的加入船上,最后合并一起就是最大的装载重量。我还加入一个数组记录集装箱的序号,可以求出是哪个集装箱加入了船上。

装载的不足我觉得这样的贪心策略,不够灵活,排序后最轻的加入,并不代表能刚刚好装满最大重量。如果剩三个物品,最轻和最重刚好能装满,但是这样的策略就是把最轻和第二重的加入,并没有装满,最后空出来的位置就浪费了。需要优化贪心策略。我也没想清楚。

背包问题

我们选第三种策略,给每件物品赋予权重=价值/重量,并且按照物品的权重降序排序,依次将物品装入背包。先选取比值最大的物品。比较其重量是否小于背包容量,如果小,就放入,如果大于背包容量,就对其进行切割。循环第一步,直到背包容量等于0。我觉得这样的贪心策略就很完美解决背包问题,不怕装不满,也能收益最大化,在装载问题的不足也能解决。但是贪心算法不能解决0-1背包问题,0-1背包不能分割不能用这样的策略。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
装载问题背包问题都是经典的贪心算法问题。装载问题是指有一批集装箱需要装载到船上,每个集装箱有自己的重量和体积,船有自己的载重量和容积限制,需要确定如何选择集装箱进行装载,使得船的载重量和容积限制最大化。背包问题是指有一批物品需要放入一个容量为V的背包中,每个物品有自己的重量和价值,需要确定如何选择物品放入背包中,使得背包中物品的总价值最大化。 装载问题背包问题都具有贪心选择性质,即每次选择当前看起来最优的集装箱或物品。但是,背包问题还具有最优子结构性质,即子问题的最优解可以推导出原问题的最优解。因此,背包问题可以用贪心算法求解,而装载问题则不能。 下面是装载问题背包问题贪心算法实现装载问题: 假设船的载重量为C,有n个集装箱需要装载,每个集装箱的重量为wi。按照重量从大到小排序,依次选择集装箱进行装载,直到船的载重量达到C或者所有集装箱都已经装载完毕。 ```python def loading_problem(C, w): w.sort(reverse=True) n = len(w) i = 0 while C > 0 and i < n: if w[i] <= C: C -= w[i] i += 1 else: break return i ``` 背包问题: 假设有n个物品需要放入容量为V的背包中,每个物品的重量为wi,价值为vi。按照单位重量的价值从大到小排序,依次选择物品放入背包中,直到背包容量达到V或者所有物品都已经放入背包中。 ```python def knapsack_problem(V, w, v): n = len(w) unit_value = [(v[i] / w[i], i) for i in range(n)] unit_value.sort(reverse=True) i = 0 value = 0 while V > 0 and i < n: j = unit_value[i][1] if w[j] <= V: V -= w[j] value += v[j] i += 1 else: value += V * unit_value[i][0] V = 0 return value ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值