• 贪心算法(1)--经典贪心算法


    目录

    一、活动安排问题

    二、最优装载问题

    三、分数背包问题

    四、多机调度问题


    一、活动安排问题

    1、策略

            活动安排问题:设有n个活动的集合E={1,2,...,n},每个活动i都有一个使用该资源的起始时间s_i和一个结束时间f_i,且s_i<f_i。如果选择了活动i则它在时间区间[s_i,f_i)内占用资源,如何在有限的时间内选择最多的活动方案安排。

            解法按结束时间优先的贪心算法。

    (1) 如果活动i和活动j能够相容,假设活动i在活动j之前,那么一定有f_i\leqslant s_j

    (2)按照f_i序列对f_is_i同时进行排序,保证两者对应。排序可以使用快速排序、归并排序和堆排复杂度为O(nlogn)。

    (3)第1个活动f_i最小,所以进入活动安排,其他如果存在s_j\geqslant f_i,则i=j,移动活动安排。

           给定一个活动序列 i,s_i,f_i的关系:

    2、代码 

    1. //活动安排
    2. import java.util.Scanner;
    3. public class activityarrangement {
    4. public static void main(String[] args)
    5. {
    6. int n=new Scanner(System.in).nextInt();
    7. int s[]=new int[n];
    8. int f[]=new int[n];
    9. for(int i=0;i
    10. s[i]=new Scanner(System.in).nextInt();
    11. for(int i=0;i
    12. f[i]=new Scanner(System.in).nextInt();
    13. quickSort(f,s, 0, n-1);
    14. GreedySelector(s,f);
    15. }
    16. public static void GreedySelector(int s[],int f[])
    17. {
    18. System.out.println(s[0]+" "+f[0]);
    19. int j=0;
    20. for(int i=1;i
    21. {
    22. if(s[i]>=f[j])
    23. {
    24. System.out.println(s[i]+" "+f[i]);
    25. j=i;
    26. }
    27. }
    28. }

    二、最优装载问题

    1、策略

            有一批集装箱要装上一艘载重为c的轮船,集装箱i的重量为w_i,要求装载体积不受限制情况下,将尽可能多的集装箱装上轮船。

            利用贪心算法重量最轻的集装箱优先装载,直到轮船载重无法继续装入集装箱。

            排序方法可以使用快排、归排和堆排来降低时间复杂度。

            约束条件和目标函数如下:

            例题如下: 

    2、代码 

    1. //最优装载问题
    2. public static void main(String []args)
    3. {
    4. int c=400;
    5. int weights[]={100,200,50,90,150,50,20,80};
    6. quickSort(weights,0,weights.length-1);
    7. System.out.println(load(weights,c));
    8. }
    9. public static int load(int weights[],int c)
    10. {
    11. int tmp=c;
    12. for(int i=0;i
    13. {
    14. if(c>weights[i])
    15. {
    16. c-=weights[i];
    17. }
    18. }
    19. return tmp-c;
    20. }

    三、分数背包问题

    1、策略

            分数背包问题:在0-1背包的问题基础上,可以每个物品装一部分,即0~1背包问题,要求在有限的容量基础上,求解装有物品的最高总价值。

            策略:以单位重量价值最高的优先的贪心算法。

            建立a数组(单位重量下价值),以a数组为排序依据,同时排序a,w,v数组,计算a数组较大值优先的情况下能产生的最大总价值。

            例题如下:

    2、代码

    (省略排序过程)

    1. //分数背包问题
    2. public class dividebackage {
    3. public static void main(String[] args)
    4. {
    5. int n=3;
    6. int c=20;
    7. double w[]={18,15,10};
    8. double v[]={25,24,15};
    9. double a[]=new double[n];
    10. for(int i=0;i
    11. a[i]=v[i]/w[i];
    12. quickSort(a,w,v,0,w.length-1);
    13. System.out.println(maximum(a,w,v,c));
    14. }
    15. public static double maximum(double a[],double w[],double v[],int c)
    16. {
    17. double value=0;
    18. int weight=0;
    19. for(int i=a.length-1;i>=0;i--)
    20. {
    21. if((c-weight)>=w[i])
    22. {
    23. value+=v[i];
    24. weight+=w[i];
    25. }
    26. else
    27. {
    28. value+=v[i]*(c-weight)/w[i];
    29. break;
    30. }
    31. }
    32. return value;
    33. }
    34. }

    四、多机调度问题

    1、概述

            多机调度问题:设有n个独立作业,由m台相同机器进行加工处理,作业i所需的处理时间为t_i,每个作业均可以在任何一台机器上加工处理,但不可间断、拆分。设计一种算法,使得n个作业在尽可能短的时间内由m台机器加工处理完成。

            策略:按任务时间较长的进行贪心算法,设定time,p,d,m,s五个数组(定义看下面代码注释),首先对time数组和p数组按任务时间降序排序(快排),调度问题为添加任务和时间推移两个阶段循环进行,直到任务不再添加,所有机器还需占用时间数为0,则退出调度问题。

            添加任务:遍历每一个机器,若当前机器m还需占用时间为0,且仍有任务i需要添加,则将任务i添加到机器m,机器m的所做任务数加一,机器m执行任务添加任务i编号。

            时间推移:时间后移一,每个任务的还需所占用时间减一,若每个机器的所占用时间都为0且没有新任务添加,则退出调度问题,返回当前时间。若存在机器i所占用时间为0,但仍有其他机器任务未结束,则机器i占用时间不再减少,避免出现负数。

            下面例题解决效果:

    2、代码 

    1. //多机调度问题
    2. public class multimachine {
    3. public static void main(String[] args)
    4. {
    5. int time[]={2,14,4,16,6,5,3}; //每个任务所占时间
    6. int p[]={1,2,3,4,5,6,7}; //任务编号
    7. int d[]={0,0,0}; //当前机器还需占用时间数
    8. int m[]={0,0,0}; //每个机器执行了几个任务
    9. int s[][]=new int[d.length][time.length]; //每个机器执行了哪些任务
    10. //对时间列和任务编号进行重新排序
    11. quickSort(time,p,0,time.length-1);
    12. //输出多机调度总时间
    13. deploy(time,p,d,s,m);
    14. //输出每个机器执行了哪些任务
    15. for(int i=0;i
    16. {
    17. for(int j=0;j
    18. {
    19. if(s[i][j]==0)
    20. break;
    21. System.out.print(s[i][j]+" ");
    22. }
    23. System.out.println("");
    24. }
    25. }
    26. public static void deploy(int time[],int p[],int d[],int s[][],int m[])
    27. {
    28. int tot=0;
    29. int c=0; //总作业序列顺序执行到几个
    30. while(true)
    31. {
    32. //进入任务,增加每个机器的所占用时间
    33. for(int i=0;i
    34. {
    35. if(d[i]==0&&c
    36. {
    37. d[i]+=time[c];
    38. s[i][m[i]++]=p[c++];
    39. }
    40. }
    41. tot+=1;
    42. int zero=0;
    43. //时间推移加一,减少每个机器的所占用时间
    44. for(int i=0;i
    45. {
    46. if(d[i]==0)
    47. break;
    48. d[i]--;
    49. zero+=d[i];
    50. }
    51. //若每个机器都为0,且没有任务继续添加,则终止调度
    52. if(zero==0)
    53. break;
    54. }
    55. System.out.println(tot);
    56. }
  • 相关阅读:
    PCL 最小中值平方法拟合平面
    JOOQ 报错 StackOverflowError
    Spring——Spring核心(IoC)控制反转详细说明
    GALIL运动控制卡维修控制器维修DMC-1840
    wsl不能启动 - 参考的对象类型不支持尝试的操作。
    Docker----harbor服务
    学会Redis这一篇就够了(1)
    Ubuntu开机黑屏原因及解决(recovery Mode)
    【无标题】
    测试平台系列(98) 完善后置条件功能
  • 原文地址:https://blog.csdn.net/m0_60177079/article/details/133934303