贪心算法(13):书架问题

Posted 中学生编程与信息学竞赛自学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心算法(13):书架问题相关的知识,希望对你有一定的参考价值。

本课程是从少年编程网转载的课程,目标是向中学生详细介绍计构和算法。编程学习最好使用计算机,请登陆 www.3dian14.org (免费注册,免费学习)。


本课继续讲解贪心算法的习题:书架问题。


有一个书房。现在要订购一批书架,这些书架背靠书房的某一面墙安放。假设该墙壁的长度为w,而书架有两种类型,它们的长度分别为m和n。


请确定需要订购的每种类型书架的数量,使得它们靠墙安放后,空出墙壁的长度最小。并且注意,由于较长的书架比较便宜,所以首选较长的书架。不过成本是次要因素,首要任务还是尽量减少墙壁的空余长度。


【例题1】

输入 : 墙壁长度 w = 24   而两种书架的长度分别是  m = 3     n = 5

输出 :  订购这两种类型的书架数量分别为3和3。

也就是每种书架的数量都为3个。这样书架排列起来的总长度


 3*m + 3*n = 3*3 + 3*5 = 24 = w

贪心算法(13):书架问题

正好排满墙壁,不留任何空余空间,因此剩余空间是0


另外一种方案是长度为m的书架为8而长度为n的书架为0个,也就是书架排列的总长度是 

贪心算法(13):书架问题

 8*m + 0*n = 24 + 0 = 25 = w


也正好排满墙壁,剩余空间也是0。但是第一种方案用了3个长度为5的大书架,而第二种方案没有用到长度为5的书架,所以第一种方案比较便宜,正确答案是第一种方案。


【例题2】

输入 : 墙壁长度 w = 29   而两种书架的长度分别是  m = 3     n = 9

输出 :  订购这两种类型的书架数量分别为多少?

贪心算法(13):书架问题

思考:如何解决这个问题?如果你看了之前的贪心算法的课件,应该不难吧?

贪心算法(13):书架问题



贪心算法(13):书架问题

 算法描述


一种简单而有效的方法是尝试适合墙壁长度的所有可能的书架组合。同时为了节省成本,我们要优先使用大的书架。


算法如下:


  1. 从0 开始,先逐个增加大书架的数目,直到再无法放置大书架或者大书架用完为止

  2. 对于选定的每种大书架的数目,计算剩余空间以及剩余空间最多能安放的小书架数目

  3. 对于上述选定的每种大书架和小书架的组合,我们计算它的空余空间

  4. 从上述所有组合种选出空余空间最少的组合,若空余空间相同,则优先选用大书架更多的组合方案



代码的实现


上述算法C++实现代码如下,为简化编程,用了C++的STL。


// C++程序实现书架放置问题

#include<bits/stdc++.h> 

using namespace std; 

  

void minSpacePreferLarge(int wall, int m, int n) 

    // 初始化输出方案的变量,

    //注意num_m为较短长度的书架数目

    //num_n为较长长度的书架数目

    //min_empty对应该输出方案的剩余空间

    int num_m = 0, num_n = 0, min_empty = wall; 

  

    // p和q分别是长度为m的书架和长度为n的书架的个数 

    // rem是墙壁的空余长度

    int p = 0, q = 0, rem; 

  

    while (wall >= n) 

    { 

        //增加一个长度为 n的书架 

        q += 1; 

        wall = wall - n; 

  

        // 在剩余墙壁空间上尽可能放置最多的长度为m的书架 

        p = wall / m; 

        rem = wall % m; 

  

        // 如果当前的方案比之前保留方案的剩余空间更小,则 

        // 把输出方案更新为当前方案 

        if (rem <= min_empty) 

        { 

            num_m = p; 

            num_n = q; 

            min_empty = rem; 

        } 

    } 

  

    //输出结果,依次为较短的书架个数、较长的书架个数

    //以及最后墙壁剩余的空间

    cout << num_m << " " << num_n << " "

        << min_empty << endl; 

  

// Driver code 

int main() 

    int wall = 24, m = 3, n = 5; 

    if (m<n)

          minSpacePreferLarge(wall, m, n);

    else

          minSpacePreferLarge(wall, n, m);


    return 0; 


下面的动图描述了应用上述算法解决【例题2】的过程。



请点击阅读原文来观看动画交互课件。


以上是关于贪心算法(13):书架问题的主要内容,如果未能解决你的问题,请参考以下文章

NOIP实用算法-贪心算法

贪心算法最大整数

47.贪心算法之三:如果可以预知未来,股票最佳买卖时机问题

搞定大厂算法面试之leetcode精讲4.贪心

贪心算法如何贪心

python 贪心算法例子