当前位置: 首页 > news >正文

算法 - 贪心算法

简介:

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

思想:

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

简单的应用1:剪绳子

问题描述

给你一个长度为n的绳子,请把绳子剪成m段(m,n都是整数,且都大于1)每段绳子的长度即为K[0],K[1],K[2]…K[m]。请问K[0]*k[1]…*k[m]可能的最大乘积是多少?

解决思路

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

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

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));
}

递归法

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代码实现

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代码实现

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;}elseb[i]=false;}for(int i=1;i<b.length;i++)System.out.println(b[i]);
}
http://www.dtcms.com/a/319741.html

相关文章:

  • 计网学习笔记第3章 数据链路层层(灰灰题库)
  • 冷库设备远程监控物联网+省电节能解决方案
  • linux下实现System V消息队列实现任意结构体传输
  • 具身智能,正在翻越三座大山
  • 计算机毕业设计java疫情开放下的新冠信息共享平台 基于Java的社区疫情防控人员流动管理系统 疫情防控期间社区人员动态管理系统
  • 范数的定义、分类与 MATLAB 应用实践
  • 解决React白板应用中的画布内容丢失问题
  • 3363. 最多可收集的水果数目
  • 关键字 - 第二讲
  • Spring AI + Redis:构建高效AI应用缓存方案
  • 【物联网】基于树莓派的物联网开发【25】——树莓派安装Grafana与Influxdb无缝集成
  • 在 Linux 系统上安装 Docker 的步骤如下(以 Ubuntu/Debian为例)
  • 前缀和
  • 简洁明了的讲明什么是哈希(hash)函数
  • [激光原理与应用-170]:测量仪器 - 能量型 - 光功率计的工作原理与内部功能模块组成
  • 【第7话:相机模型3】自动驾驶IPM图像投影拼接技术详解及代码示例
  • 直连微软,下载速度达18M/S
  • Mysql 单行函数 聚合函数
  • MySQL聚簇索引与非聚簇索引详解
  • 北京企业数据防泄漏指南:5款适合北方市场的安全加密工具评测
  • 【华为机试】332. 重新安排行程
  • MySQL——黑马
  • STM32U5 周期性异常复位问题分析
  • 【MyQSL】库 表—基操
  • 性能优化——GPU的影响
  • [C++20]协程:语义、调度与异步 | Reactor 模式
  • Kafka原理--主题、分区、消费者的关系
  • windows内核研究(内存管理-线性地址的管理)
  • 【PHP 中的 `use` 关键字完全指南】
  • Linux图文理解进程