【趣学算法】Day2 贪心算法——最优装载问题

简介: 【趣学算法】Day2 贪心算法——最优装载问题

一、贪心算法


(1)介绍


贪心算法总是做出当前最好的选择,期望通过局部最优解选择,从而得到全局最优的解决方案。


(2)注意事项


1)一旦做出选择,就不可以回溯。

2)有可能得不到最优解,而是得到最优解的近似值。

3)选择什么样的贪心策略直接决定了算法的好坏。

(3)性质

人们通过实践发现,利用贪心算法求解的问题往往具有两个重要的性质:贪心选择和最优子结构。只要满足这两个性质,就可以使用贪心算法。

1)贪心选择

贪心选择是指原问题的整体最优解可以通过一系列局部最优的选择得到:先做出当前最优的选择,将原问题变为一个相似却规模更小的子问题,而后的每一步都是当前最优的选择。这种选择依赖于已做出的选择,但不依赖于未做出的选择。

2)最优子结构

       最优子结构是指原问题的最优解包含子问题的最优解。贪心算法通过一系列的局部最优解(子问题的最优解)得到全局最优解(原问题的最优解),如果原问题的最优解和子问题的最优解没有关系,则求解子问题没有任何意义,无法采用贪心算法。


二、最优装载问题

       海盗们截获一艘装满各种各样古董的货船,每一件古董都价值连城,但一旦打碎就会失去其原有的价值。海盗船虽然足够大,但载重量是有限的。海盗船的载重量为W,每件古董的重量为wi,如何才能把尽可能多的古董装上海盗船呢。


(1)古董重量排序

海盗船的载重量w为30。

排序前的古董重量为:

w[i] = {4, 10, 7, 11, 3, 5, 14, 2};

排序后的古董重量为:

w[i] = {2, 3, 4, 5, 7, 10, 11, 14};


(2)贪心策略选择

按照贪心策略,每次选择重量最小的古董装入海盗船(tmp代表已装入的古董重量,ans代表已装入的古董重量)。

1)选择排序后的第1个古董,装入重量tmp = 2,没有超出载重量,ans = 1;

2)选择排序后的第2个古董,装入重量tmp = 2 + 3 = 5,没有超出载重量,ans = 2;


3)选择排序后的第3个古董,装入重量tmp = 5 + 4 = 9,没有超出载重量,ans = 3;


4)选择排序后的第4个古董,装入重量tmp = 9 + 5 = 14,没有超出载重量,ans = 4;


5)选择排序后的第5个古董,装入重量tmp = 14 + 7 = 21,没有超出载重量,ans = 5;


6)选择排序后的第6个古董,装入重量tmp = 21 + 10 =31,没有超出载重量,ans = 6;


当第六次装入古董时可以发现已经超出了船的载重量,所以古董最多装ans = 5个

模板代码

(1)分析

       首先使用变量ans记录装入海盗船的古董数量,并使用变量tmp暂存装入海盗船的古董重量。然后依次检查每个古董,对tmp加上改古董的重量,如果小于或的等于载重w,责令ans++,否则退出。

(2)伪代码


int solve1(int n,double W){
  double tmp=0.0;//tmp为已装载到船上的古董重量
    int ans=0; //ans为已装载的古董个数,初始化为0
    for(int i=0;i<n;i++){
        tmp+=w[i];
        if(tmp<=W)
            ans++;
        else
            break;
    }
    return ans;
} 

代码优化

(1)分析


实际上,不需要在每次判断是否超出载重时执行ans++,而是可以初始化ans = n。如果已装入海盗船的古董重量tmp大于或等于载重量w,则判断是否刚好等于载重量w并令ans = i + 1,否则令ans = i并退出。这样就只有最后一次才满足条件,ans只需要赋值一次即可,或者所有古董都被装入(初始值n)。


(2)伪代码

int solve2(int n,double w){//优化算法 
  double tmp=0.0;//tmp为已装载到船上的古董重量
  int ans=n; //ans为已装载的古董个数,初始化为n
    for(int i=0;i<n;i++){
        tmp+=w[i];
        if(tmp>=w){//最后一次才满足条件 
          if(tmp==w)
            ans=i+1;
          else
            ans=i;
          break;
    }     
    }
    return ans;
}


三、 程序实现

注:程序由Java语言实现

public class algorithm02 {
    public static void main(String[] args) {
        int[] w = {4, 10, 7, 11, 3, 5, 14, 2};
        int W = 30; // 船的载重量
        int temp;
        for (int i = 0; i < w.length-1; i++) {
            for (int j = 0; j < w.length - i - 1; j++) {
                if (w[j] > w[j + 1]) {
                    temp = w[j];
                    w[j] = w[j + 1];
                    w[j + 1] = temp;
                }
            }
        }
        System.out.println("古董重量排序后为:");
        for (int j = 0; j < w.length; j++) {
            System.out.print(w[j] + " ");
        }
            add02 a2 = new add02();
            int ans = a2.solve2(8 , W , w);
            System.out.println("\n总共装入了" + ans + "个古董");
    }
}
// add02类
public class add02 {
    public int solve2(int n , int W ,int w[]){//优化算法
        double tmp = 0.0;//tmp为已装载到船上的古董重量
        int ans = 0; //ans为已装载的古董个数,初始化为n
        for(int i = 0; i < n; i++){
            tmp += w[i];
            if(tmp >= W){//最后一次才满足条件
                if(tmp == W)
                    ans = i+1;
                else
                    ans = i;
                break;
            }
        }
        return ans;
    }
}


得到结果为:


0a09a4149e75402ca3f7e38f61463aee.png


因为船的载重量为30,所以在装入第五个古董后就无法装入第六个了。

相关文章
|
3月前
|
算法 C++ Python
数据结构与算法===贪心算法
数据结构与算法===贪心算法
|
1月前
|
算法
【算法】贪心算法——柠檬水找零
【算法】贪心算法——柠檬水找零
|
1月前
|
算法
【算法】贪心算法简介
【算法】贪心算法简介
|
2月前
|
机器学习/深度学习 数据采集 算法
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
|
2月前
|
算法 Python
Python算法高手进阶指南:分治法、贪心算法、动态规划,掌握它们,算法难题迎刃而解!
【7月更文挑战第10天】探索Python算法的精华:分治法(如归并排序)、贪心策略(如找零钱问题)和动态规划(解复杂问题)。通过示例代码揭示它们如何优化问题解决,提升编程技能。掌握这些策略,攀登技术巅峰。
62 2
|
2月前
|
存储 算法 Python
Python算法界的秘密武器:分治法巧解难题,贪心算法快速决策,动态规划优化未来!
【7月更文挑战第9天】Python中的分治、贪心和动态规划是三大关键算法。分治法将大问题分解为小问题求解,如归并排序;贪心算法每步选局部最优解,不保证全局最优,如找零钱;动态规划存储子问题解求全局最优,如斐波那契数列。选择合适算法能提升编程效率。
49 1
|
2月前
|
存储 算法 大数据
Python算法高手的必修课:深入理解分治法、贪心算法、动态规划,让你的代码更智能!
【7月更文挑战第9天】在Python算法学习中,分治法(如归并排序)将大问题分解为小部分递归解决;贪心算法(如货币找零)在每步选择局部最优解尝试达到全局最优;动态规划(如斐波那契数列)通过存储子问题解避免重复计算,解决重叠子问题。掌握这三种方法能提升代码效率,解决复杂问题。
35 1
|
2月前
|
算法 索引 Python
逆袭算法界!Python分治法、贪心算法、动态规划深度剖析,带你走出算法迷宫!
【7月更文挑战第8天】分治法,如快速排序,将大问题分解并合并解;贪心算法,选择局部最优解,如活动选择;动态规划,利用最优子结构避免重复计算,如斐波那契数列。Python示例展示这些算法如何解决实际问题,助你精通算法,勇闯迷宫。
30 1
|
2月前
|
算法 索引 Python
Python算法设计与分析大揭秘:分治法、贪心算法、动态规划...掌握它们,让你的编程之路更加顺畅!
【7月更文挑战第8天】探索Python中的三大算法:分治(如快速排序)、贪心(活动选择)和动态规划(0-1背包问题)。分治法将问题分解求解再合并;贪心策略逐步求局部最优;动态规划通过记忆子问题解避免重复计算。掌握这些算法,提升编程效率与解决问题能力。
32 1
|
2月前
|
算法
基于Dijkstra算法的最优行驶路线搜索matlab仿真,以实际城市复杂路线为例进行测试
使用MATLAB2022a实现的Dijkstra算法在城市地图上搜索最优行驶路线的仿真。用户通过鼠标点击设定起点和终点,算法规划路径并显示长度。测试显示,尽管在某些复杂情况下计算路径可能与实际有偏差,但多数场景下Dijkstra算法能找到接近最短路径。核心代码包括图的显示、用户交互及Dijkstra算法实现。算法基于图论,不断更新未访问节点的最短路径。测试结果证明其在简单路线及多数复杂城市路况下表现良好,但在交通拥堵等特殊情况下需结合其他数据提升准确性。