算法 - 贪心算法

简介:

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

思想:

把问题分解为多个子问题,只要依次求出子问题的最优解,就能得到最终问题的最优解。即,只需要考虑局部最优,就能得到全局最优。

简单的应用1:剪绳子

问题描述

给你一个长度为n的绳子,请把绳子剪成m段(m,n都是整数,且都大于1)每段绳子的长度即为K0,K1,K2...Km。请问K0*k1...*km可能的最大乘积是多少?

解决思路

如果我们按照如下的策略剪绳子,则得到的各段绳子的长度的乘积将最大;当n>=5,我们尽可能地剪长度为3的绳子;当剩下的绳子长度为4时,把绳子剪为长度为2的绳子.

贪心算法的核心是通过局部最优解来得到全局最优解,对于分割问题来说,要使乘积最大,该问题的贪心思想是尽可能去剪为长度为3的绳子!

Java代码实现

迭代法

java 复制代码
public static int greedy_cut_rope_1(int n) {
   if(n<2)
       return 0;
   if(n==2)
       return 1;
   if(n==3)
       return 2;
   //尽可能多地去减长度为3的绳子段
   int timesOf3 = n/3;
   //当绳子最后剩下的长度为4的时候,不能再去剪去长度为3的绳子段
   if(n-timesOf3*3==1)
       timesOf3-=1;
   int timesOf2 =(n-timesOf3*3)/2;
   return (int) (Math.pow(3,timesOf3)*Math.pow(2,timesOf2));
}

递归法

java 复制代码
public static int greedy_cut_rope(int n) {
   if(n==2)
       return 2;
   if(n==3)
       return 3;
   if(n<2)
       return 1;
   //int timesOf3 = n/3;
   if(n==4)
       return 4;
   return 3*greedy_cut_rope(n-3);
}

简单的应用2:背包问题

问题描述

给定N个物品和一个容量为C的背包,物品i的重量为Wi,其价值为Vi,背包问题是如何选择装入背包的物品,使得装入背包中物品的总价值最大。注意在背包问题中,可以将某种物品的一部分装入背包中,但是不可以重复装入。

解决思路

三种贪心思想:

选择价值最大的物品

选择重量最轻的物品

选择单位重量价值最大的物品

毫无疑问,我们当然选择第三种咯。先把性价比最高的全部装入,最后不足全部装入的部分装入。

Java代码实现

java 复制代码
public static int greedy_knapSack(int[] w,int[] v,int n,int c) {
   //  假设物品已按单位重量降序排列
   double[] x = new double[10];
   int maxValue =0;
   int i;
   for(i=0;w[i]<c;i++) {
       x[i]=1; //将物品 i 装入背包
       maxValue+=v[i];
       c=c-w[i]; // 背包剩余数量
   }
   x[i]=(double)c/w[i];    //物品i装入一部分
   maxValue+=x[i]*v[i];
   return maxValue;    //返回背包获得的价值
}

简单的应用3:活动选择问题

问题描述

假设有一个需要使某一资源的n个活动组成的集合S={a1,a2,a3...an}。该资源一次只能被一个活动占用,每个活动ai有一个开始时间Si和结束时间Fi,且0<=Si<Fi<∞。一旦被选择后,活动ai就占据半开时间区间[Si,Fi)。如果区间[Si,Fi)与 [Sj,Fj)互不重叠,称活动ai与aj是兼容的。活动选择问题就是要选择出一个由互相兼容的问题组成的最大集合。

讨论下面的活动集合S,其中各活动已按结束时间的单调递增顺序进行了排序:

解决思路

对于任意非空子问题Sij,设am是Sij中具有最早结束时间的活动:

fm=min{fk:ak∈Sij}

那么:

1.活动am在Sij的某最大兼容活动子集中被使用。

2.子问题Sim为空,所以选择am使子问题Smj为唯一可能非空的子问题。

在解决子问题时,选择am是一个可被合法调度、具有最早结束时间的活动。从直觉上来看,这种活动选择方法是一种贪婪技术,他给后面剩下的待调度任务留下了尽可能多的机会。也就是说,此处的贪心选择使得剩下的、未调度的时间最大化。

Java代码实现

java 复制代码
public static void greedy_activity_selector(int[] s,int[] f,boolean[] b) {
   int n = s.length-1;
   b[1]=true;
   int j=1;
   for(int i =2;i<=n;i++) {
       if(s[i]>f[j]) {
           b[i]=true;
           j=i;
       }else
           b[i]=false;
   }
   for(int i=1;i<b.length;i++)
       System.out.println(b[i]);
}
相关推荐
江畔柳前堤4 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore5 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考7 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX8 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面8 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号8 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽9 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI9 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者10 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者10 小时前
【征程6】校准量化中HistogramObserver解析
算法