贪心算法-MATLAB实现

本文详细介绍了贪心算法的基本原理、性质,并通过找零钱问题、空瓶换酒问题和活动安排问题三个实例展示了贪心算法在Matlab中的实现。在找零钱问题中,从最大面值的硬币开始找,以减少硬币数量;在空瓶换酒问题中,最大化利用空瓶换取更多的酒;在活动安排问题中,按活动结束时间从早到晚进行安排,确保资源利用率最大化。贪心算法虽然在某些问题上效果良好,但也存在局限性,不适用于所有最优化问题。
摘要由CSDN通过智能技术生成

贪心算法的基本原理

贪心算法是使所做的选择看起来都是当前最佳的,期望通过所做的局部最优选择来产生出一个全局最优解。

贪心算法的性质

  1. 贪心选择:在做贪心选择时,应满足可行性,即必须满足问题的约束条件。
  2. 局部最优:通过做一系列的选择来给出某一问题的最优解。对算法中的每一个决策点,做一个当时最佳的选择。
  3. 子结构结果:贪心算法所做的当前选择可能要依赖于已经做出的所有选择,但不依赖于有待于做出的选择或子问题的解。

例题

找零钱问题

题目:假设有7种硬币,面值分别为0.01元、0.02元、 0.05元、 0.1元、 0.2元、 0.5元、 1元。要找6.66元,问如何找钱才能使找出的硬币个数最少?
核心思想:每一次找钱都从零钱面值最大的算起,以确保每次找出的硬币数目最少
基本思路:

  1. 读取硬币和零钱的数值
  2. 从面值最大的硬币开始找起,逐步递减直到零钱值为零

MATLAB代码如下:

%贪心算法解决找零钱问题
% greedy algorithm(GA)贪心/贪婪算法
d=[0.01 0.02 0.05 0.5 0.1 0.2 1]%输入零钱面值,存入d数组中
%将数组d排序,使得其零钱面值为从小到大
value=sort(d)
a= input('请输入需要找的零钱数:')%a表示需要找的零钱数
i=length(value)%用length函数计算d数组的长度
while i>0
    if a>=value(i) %从面值最大的开始找,d[i]此时i=6 i的值是最大的,d[i]是最大的
        n=fix(a/value(i))%fix函数用于向下取整,n的含义是需要找的零钱个数
        a=round(a-n*value(i),2)%round保留两位小数
        X=sprintf('找了%d个%.2f元硬币',n,value(i))
        disp(X)
    end
    i=i-1
end

空瓶换酒问题

题目:小区便利店正在促销,用 3 个空酒瓶可以兑换一瓶新酒。你购入了 5 瓶酒。如果喝掉了酒瓶中的酒,那么酒瓶就会变成空的。请你计算最多能喝到多少瓶酒?
核心思想:每一次换酒都尽最大可能换最多的酒
基本思路:

  1. 设置交换规则并读取初值
  2. 记录剩余酒瓶的数量、喝到的酒的数量,当剩余酒瓶已经不能换酒时,停止循环

空瓶换酒问题示意图如下:
在这里插入图片描述MATLAB代码如下:

%贪心算法解决空瓶换酒问题
% greedy algorithm(GA)贪心/贪婪算法
a=1
while a==1
    %购入了 n 瓶酒
    n = input('你现在有几瓶酒?');
    %用 m 个空酒瓶可以兑换一瓶新酒
    m = input('几个酒瓶可以换一瓶酒?');
    if m<=1
        disp('输入错误 请重新输入')
        a=1
    else 
        a=0
    end
end
%初始化
count = n;  % 喝到酒的数目
e = n;  % 空瓶数目
%初始时,空瓶数量等于已有酒的数量,还未开始换酒
while fix(e / m) ~= 0 %fix函数向下取整,当手里有的空瓶数量一瓶酒的换不了了就结束循环
    bottle = fix(e / m);  % 利用当前空瓶最大限度地兑换酒,得到当前酒的数目
    count = count + bottle;  % 更新喝到酒的数目
    e = mod(e,m) + bottle; %更新空瓶数目:空瓶=兑换后剩余空瓶+兑换得到的酒瓶   mod函数:返回 e 除以 m 后的余数
end
X=sprintf('一共可以喝到%d瓶酒',count)
disp(X)

当酒的瓶盖也可以换酒时,则需考虑两个数量的变化,找到最大换酒数量,MATLAB代码如下:

%贪心算法解决空瓶换酒问题2.0% greedy algorithm(GA)贪心/贪婪算法
%初始化
clc;clear;
n=20%共有n瓶酒
m=2%用 m 个空酒瓶可以兑换一瓶新酒
q=3%用q个瓶盖可以换1瓶酒
count = n;  % 喝到酒的数目
e = n;  % 空瓶数目
f = n;  %瓶盖数目
while (fix(e / m) ~= 0 )||(fix(f/q)~=0)%fix函数向下取整,当手里有的空瓶数量一瓶酒的换不了了就结束循环
    if fix(e / m) ~= 0
        bottle_e = fix(e / m) % 利用当前空瓶最大限度地兑换酒,得到当前酒的数目
    end
    if fix(f / q) ~= 0
        bottle_f = fix(f / q)
        % 更新喝到酒的数
    end
    e = mod(e,m) + bottle_e+bottle_f; %更新空瓶数目:空瓶=兑换后剩余空瓶+兑换得到的酒瓶   mod函数:返回 e 除以 m 后的余数
    f = mod(f,q) + bottle_f+bottle_e; %更新瓶盖数目:瓶盖=兑换后剩余瓶盖+兑换得到的瓶盖
    count = count + bottle_e+bottle_f;
    bottle_e=0
    bottle_f=0
end
X=sprintf('最终喝到%d瓶酒',count)%最终喝到酒的瓶数
disp(X)

活动安排问题

题目:设有n个活动a1, a2…, an,每个活动都要求使用同一资源,而同一时间内只允许一个活动使用这一资源。已知活动ai,要求使用该资源的起始时间为si,结束时间为fi,且si<= fi。要求在a1, a2, …, an中选出最大的相容活动子集。
核心思想:按结束时间从早到晚安排活动,每次选择与已选出的活动相容的结束时间尽可能早的活动。以保证每次为资源留下尽可能多的时间以容纳其它活动。
基本思路:

  1. 读取活动的数据并排序
  2. 找出相容活动子集
  3. 输出结果

活动安排问题示意图如下:
在这里插入图片描述MATLAB代码如下:

%贪心算法解决活动安排问题
% greedy algorithm(GA)贪心/贪婪算法
s=[1 2 2 3 5 ]%s为活动开始时间
f=[5 6 8 9 10]%f为活动结束时间,并且s和f一一对应
n=5%n为活动的数量(1,5) (2,6) (2,8) (3,9) (5,10)
%排序,以活动最早结束的时间为标准,将活动排序,结束时间越早,越排在前面
[JL,Index]=sort(f)
f=JL
s=s(Index)
 for i =1:length(f)
     a(i)=[true];
 end
j = 1
for i =2:n
    %如果下一个活动的开始时间大于等于上个活动的结束时间,最关键的语句
    if s(i)>= f(j)
        a(i)= true
        j = i
    else
        a(i) = false
    end
end
  disp('安排的活动有')
for i =1:length(a)
    if a(i)
        X=sprintf('开始时间为%d,结束时间为%d的活动%d',s(i),f(i),i);
        disp(X)
    end
end

贪心算法的局限性

贪心法可以解决一些最优化问题,如:求最小生成树、求哈夫曼编码……对于其他问题,贪心法一般不能得到我们所要求的答案。一旦一个问题可以通过贪心法来解决,那么贪心法一般是解决这个问题的最好办法。 由于贪心法的高效性以及其所求得的答案比较接近最优结果,贪心法也可以用作辅助算法或者直接解决一些要求结果不特别精确的问题。在不同情况,选择最优的解,可能会导致辛普森悖论(Simpson’s Paradox),不一定出现最优的解。

  • 6
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值