贪心算法经典问题:活动安排,背包问题,最优装载,单源最短路径 Dijiksra,找零钱问题,多机调度

合集下载

JS基于贪心算法解决背包问题示例

JS基于贪心算法解决背包问题示例

JS基于贪⼼算法解决背包问题⽰例本⽂实例讲述了JS基于贪⼼算法解决背包问题。

分享给⼤家供⼤家参考,具体如下:贪⼼算法:在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

寻找最优解的过程,⽬的是得到当前最优解部分背包问题:固定容积的背包能放⼊物品的总最⼤价值物品 A B C D价格 50 220 60 60尺⼨ 5 20 10 12⽐率 10 11 6 5按⽐例降序尽可能多放⼊物品function greedy(values, weights, capacity){var returnValue = 0var remainCapacity = capacityvar sortArray = []values.map((cur, index) =>{sortArray.push({'value': values[index],'weight': weights[index],'ratio': values[index]/weights[index]})})sortArray.sort(function(a, b){return b.ratio > a.ratio})console.log(sortArray)sortArray.map((cur,index) => {var num = parseInt(remainCapacity/cur.weight)console.log(num)remainCapacity -= num*cur.weightreturnValue += num*cur.value})return returnValue}var items = ['A','B','C','D']var values = [50,220,60,60]var weights = [5,20,10,12]var capacity = 32 //背包容积greedy(values, weights, capacity) // 320更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《》、《》、《》、《》、《》及《》希望本⽂所述对⼤家JavaScript程序设计有所帮助。

2 贪心算法

2 贪心算法

18
2.3 最优装载
有一批集装箱要装上一艘载重量为c的轮船。其中集 装箱i的重量为Wi。最优装载问题要求确定在装载体积不 受限制的情况下,将尽可能多的集装箱装上轮船。
1、算法描述
最优装载问题可用贪心算法求解。采用重量最轻者先 装的贪心选择策略,可产生最优装载问题的最优解。具体 算法描述如下页。
19
2
2.1 贪心算法概述
贪心算法总是作出在当前看来最好的选择。 也就是说贪心算法并不从整体最优考虑,它所作出 的选择只是在某种意义上的局部最优选择。当然, 希望贪心算法得到的最终结果也是整体最优的。
虽然贪心算法不能对所有问题都得到整体最优 解,但对许多问题它能产生整体最优解, 如单源最 短路经问题、最小生成树问题等。在一些情况下, 即使贪心算法不能得到整体最优解,其最终结果却 是最优解的近似解。
3
2.1.1贪心算法策略
贪心算法采用的是逐步构造最好优解的方法, 即总是作出在当前看来最好的选择。
4
例2.1 付款问题 找零问题。如26.8。 “贪心” 原则:尽量给顾客大面值的钱。 20、5、1、0.5、0.2、0.1 问题描述: 已知:int m[]={500,200,100,50,20,10,5,2,1}; int v; 输出:各种钞票数 int n[9], 使得
Σ n[i]*m[i]=v 且Σn[i]最小。 i=1 i=1
5
9
9
void pay(int m[],int v){ int i,r,n[9]; for(i=0;i<9;i++)n[i]=0; r=v; i=0; while (r>0) { if (m[i]<=r) { r-=m[i]; n[i]++; } else i++; } for(i=0;i<9;i++) 输出n[i]个m[i]面值的钞票。 }

贪心算法之最优装载问题

贪心算法之最优装载问题

贪⼼算法之最优装载问题贪⼼算法之最优装载问题1. 问题描述有⼀批集装箱要装上⼀艘重量为c的轮船,其中集装箱i的重量为W i。

最优装载问题要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。

2. 问题分析2.1确定贪⼼策略采⽤重量最轻者先装的贪⼼选择策略,可产⽣该问题的最优解。

2.2代码求解/*** x[] 保存最优解路径数组* w[] 集装箱重量数组* c 船的载重量* n 集装箱的数量**/void Loading(int x[], int w[], int c, int n) {// 按照集装箱重量从⼩到⼤排序sort(w, n);for (int i = 1; i <= n; i++)x[i] = 0;for (int i = 1; i <= n && w[i] <= c; i++) {x[i] = 1;c -= w[i];}}2.3贪⼼选择性质设集装箱依其重量从⼩到⼤排序,(x1,x2,…,x n)是其最优解,x i={0,1},设x k是第⼀个等于1的。

(1) 如k=1,则满⾜贪⼼选择性质(2) 如k≠1,⽤x1替换x k,构造的新解同原解最优值相同,故也是最优解,满⾜贪⼼选择性质该证明⽅法只证明了任何⼀个最优解都可以转换为第⼀个集装箱上船的最优解(满⾜贪⼼策略)。

此⽅法对⼦问题同样有效,因此可以将⼀个普通最优解转化为满⾜贪⼼策略的最优解。

如(0101)⇒(1100)2.4.最优⼦结构性质最优装载问题具有最优⼦结构性质,设1⾄n个集装箱装上船的最⼤数量为T(1,n,w),则T(1,n,w)=1+T(2,n,w−w1);因T(1,n,w)是最优值,则T(2,n,w−w i)⼀定是最优值,反证法证明之反证法:如果T(2,n,w−w1)不是该问题的最优解,则存在最优值T′(2,n,w−w1)>T(2,n,w−w1),则1+T′(2,n,w−w1)=T′(1,n,w)>T(1,n,w),这与⼤前提T(1,n,w)是最优值相⽭盾,故T(2,n,w−w1)⼀定是最优值。

贪心算法题库

贪心算法题库

贪心算法是一种在每一步选择中都采取当前情况下的局部最优选择,并希望导致结果是全局最优解的算法。

下面是一些贪心算法的题目和解答:1. 旅行商问题(Travelling Salesman Problem):问题描述:给定一个城市列表和一个距离列表,要求找出一条路径,使得路径上的所有城市都经过,且总距离最短。

贪心算法解法:首先对城市按照距离进行排序,然后从最近的两个城市开始,每次都选择距离当前位置最近的两个城市,直到遍历完所有城市。

由于贪心算法每次选择的都是当前情况下的最优解,因此最终得到的路径总距离是最短的。

2. 背包问题(Knapsack Problem):问题描述:给定一组物品,每个物品都有自己的重量和价值,要求在不超过背包总重量的情况下,如何选择物品使得背包中物品的总价值最大。

贪心算法解法:按照物品的重量对物品进行排序,然后每次选择重量最小的物品,直到背包已满或无物品可选。

由于贪心算法每次选择的都是当前情况下的最优解,因此最终得到的方案总是可以找到一个大于等于当前最优解的方案。

3. 网格找零问题(Currency Change Problem):问题描述:给定一组面值不同的硬币,要求用最少的组合方式从一定金额中找零。

贪心算法解法:首先对硬币面值进行排序,然后每次使用当前面值最小的硬币进行组合,直到金额为零或无硬币可选。

贪心算法在此问题中的思路是每次选择最小的硬币进行使用,这样可以保证找零的最小数量。

以上题目和解答只是贪心算法的一部分应用,实际上贪心算法在许多其他领域也有广泛的应用,例如网页布局优化、任务调度、网络流等等。

贪心算法的优势在于其简单易懂、易于实现,但也有其局限性,例如无法处理一些存在冲突的情况或最优解不唯一的问题。

因此在实际应用中需要根据具体问题选择合适的算法。

关于贪心算法的经典问题(算法效率or动态规划)

关于贪心算法的经典问题(算法效率or动态规划)

关于贪⼼算法的经典问题(算法效率or动态规划)如题,贪⼼算法⾪属于提⾼算法效率的⽅法,也常与动态规划的思路相挂钩或⼀同出现。

下⾯介绍⼏个经典贪⼼问题。

(参考⾃刘汝佳著《算法竞赛⼊门经典》)。

P.S.下⽂皆是我⼀个字⼀个字敲出来的,绝对“童叟⽆欺”,哈哈。

(。

⌒∇⌒) 耗费了我的很多时间,所以——希望对⼤家有帮助啊~ (=^‸^=)⼀、背包相关问题1.最优装载问题:给出N个物体,有⼀定重量。

请选择尽量多的物体,使总重量不超过C。

解法:只关⼼数量多,便把重量从⼩到⼤排序,依次选,直到装不下。

2.部分背包问题:给出N个物体,有⼀定重量和价值。

请选择⼀些物体的⼀部分使在总重量不超过C的条件下总价值最⼤。

解法:关⼼总价值⼤,物体可取部分,便优先取单位重量价值较⼤的物体。

3.乘船问题:有N个⼈,有⼀定重量。

每艘船的最⼤载重量均为C,且最多载2⼈。

请⽤最少的船装载所有⼈。

解法:关⼼数量少,要尽量使每艘船的实际载重量尽量接近于最⼤载重量。

便把重量从⼩到⼤排序,每艘船依次先载⼀个⼈,再载重量最接近船的剩余可载重量的⼈。

这样可以使眼前的消费(剩余载重量)最少。

实现:⽤2个变量 l , r 分别从两头往中间移动,l 和 r 可共乘⼀艘船,或 r ⾃⼰乘⼀艘船。

⼆、区间相关问题1.选择不相交区间:数轴上有N个开区间(Li,Ri),请选择尽量多个区间,并保证这些区间两两没有公共点。

解法:先把这些区间按找 Ri 从⼩到⼤的顺序排序,再对按序排列的每2个区间A,B分情况讨论:(1)A被B包含,选A最优;(2)A右边的⼀部分与B左边的⼀部分相交,选A最优,因为选A⽐B减少了与后⾯区间相交的可能性;(3)A、B不相交,便2个都选。

总的来说就是排序后,从左到右选第⼀个没有与前⾯已选的区间相交的区间。

O(n)。

拓展:那么如果可以⼀共覆盖两次,那该怎么选? ——也就是。

2.区间选点问题:数轴上有N个闭区间[Li,Ri],请选择尽量少的点,使得每个区间内都⾄少有⼀个点。

c++贪心算法经典例题

c++贪心算法经典例题

c++贪心算法经典例题摘要:一、贪心算法简介1.贪心算法的定义2.贪心算法的特点3.贪心算法适用的问题类型二、C++贪心算法经典例题1.背包问题a.0-1 背包问题b.完全背包问题c.动态背包问题2.最小生成树a.Kruskal 算法b.Prim 算法3.单源点最短路径a.Dijkstra 算法b.Floyd-Warshall 算法4.最长公共子序列a.贪心算法实现b.动态规划实现正文:一、贪心算法简介贪心算法(Greedy Algorithm)是一种求解最优解的方法。

它是在对问题求解时,总是做出在当前看来是最好的选择。

贪心算法并不追求整体最优解,只希望得到较为满意的解。

贪心算法的关键是贪心策略的选择,必须满足无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。

贪心算法适用的问题类型包括背包问题、最小生成树、单源点最短路径和最长公共子序列等。

二、C++贪心算法经典例题1.背包问题背包问题(Knapsack Problem)是一种典型的贪心算法问题。

它描述的是有一个背包,有一定的容量,需要装载若干物品,每个物品有一定的价值和重量,要求在不超过背包容量的前提下,如何选择装载物品使得背包中的物品总价值最大。

背包问题可以分为0-1 背包问题、完全背包问题和动态背包问题。

2.最小生成树最小生成树(Minimum Spanning Tree,简称MST)是一种图论中的算法问题。

给定一个加权连通图,求解一个生成树,使得该生成树中所有边的权值之和最小。

最小生成树的经典算法有Kruskal 算法和Prim 算法。

3.单源点最短路径单源点最短路径(Single Source Shortest Path)问题是在一个图中,从源点出发到其他所有顶点的最短路径。

经典算法包括Dijkstra 算法和Floyd-Warshall 算法。

4.最长公共子序列最长公共子序列(Longest Common Subsequence,简称LCS)问题是求两个序列中最长的公共子序列。

贪心算法和分支限界法解决单源最短路径

贪心算法和分支限界法解决单源最短路径

贪⼼算法和分⽀限界法解决单源最短路径单源最短路径计科1班朱润华 2012040732⽅法1:贪⼼算法⼀、贪⼼算法解决单源最短路径问题描述:单源最短路径描述:给定带权有向图G=(V,E),其中每条边的权是⾮负实数。

另外,还给定V中的⼀个顶点,称之为源(origin)。

现在要计算从源到其他各顶点的最短路径的长度。

这⾥的路径长度指的是到达路径各边权值之和。

Dijkstra算法是解决单源最短路径问题的贪⼼算法。

Dijkstra算法的基本思想是:设置顶点集合S并不断地做贪⼼选择来扩充集合。

⼀个顶点属于集合S当且仅当从源点到该顶点的最短路径长度已知。

贪⼼扩充就是不断在集合S中添加新的元素(顶点)。

初始时,集合S中仅含有源(origin)⼀个元素。

设curr是G的某个顶点,把从源到curr 且中间只经过集合S中顶点的路称之为从源到顶点curr的特殊路径,并且使⽤数组distance记录当前每个顶点所对应的最短路径的长度。

Dijkstra算法每次从图G中的(V-S)的集合中选取具有最短路径的顶点curr,并将curr加⼊到集合S中,同时对数组distance 进⾏必要的修改。

⼀旦S包含了所有的V中元素,distance数组就记录了从源(origin)到其他顶点的最短路径长度。

⼆、贪⼼算法思想步骤:Dijkstra算法可描述如下,其中输⼊带权有向图是G=(V,E),V={1,2,…,n},顶点v 是源。

c是⼀个⼆维数组,c[i][j]表⽰边(i,j)的权。

当(i,j)不属于E时,c[i][j]是⼀个⼤数。

dist[i]表⽰当前从源到顶点i的最短特殊路径长度。

在Dijkstra算法中做贪⼼选择时,实际上是考虑当S添加u之后,可能出现⼀条到顶点的新的特殊路,如果这条新特殊路是先经过⽼的S到达顶点u,然后从u经过⼀条边直接到达顶点i,则这种路的最短长度是dist[u]+c[u][i]。

如果dist[u]+c[u][i]1、⽤带权的邻接矩阵c来表⽰带权有向图, c[i][j]表⽰弧上的权值。

最佳装载背包问题--贪心算法

最佳装载背包问题--贪心算法

贪心法求解最佳装载背包问题描述:对于容量为c的背包进行装载,从n个物品中选择装入背包的物品,每个物品i的重量和价值分别为wi和pi。

在背包中物品的总重量不超过背包容量的前提下,求装入物品价值最高的装载法。

输入:5 20 //物品的数量和背包的容量6 3 //第一个物品的重量和价值2 5 //…3 810 67 4输出:1110.714286算法如下:#include <stdio.h>#include <stdlib.h>struct goodinfo//物品结构体{float p;//价值float w;//重量float x;//数量int flag;//标志变量};void Insertionsort(struct goodinfo goods[],int n)//将物品根据价值排序{int i,j;for(j=2;j<=n;j++){goods[0]=goods[j];//保存比较的对象i=j-1;while(goods[0].p>goods[i].p)//找到位置后退出{goods[i+1]=goods[i];//错位i--;}goods[i+1]=goods[0];//找到位置后将比较的对象覆盖}}void bag(struct goodinfo goods[],float M,int n){float cu;//剩余空间int i,j;for(i=1;i<=n;i++)goods[i].x=0;//初始化cu=M;//初始化for(i=1;i<=n;i++){if(goods[i].w>cu)break;goods[i].x=1;cu=cu-goods[i].w;}if(i<=n)goods[i].x=cu/goods[i].w;//将物品分割for(j=2;j<=n;j++)//按照物品的编号排序,便于输出goods[0]=goods[j];i=j-1;while(goods[0].flag<goods[i].flag){goods[i+1]=goods[i];i--;}goods[i+1]=goods[0];}printf("最优解为:\n");for(i=1;i<=n;i++){printf("第%d件物品要放:%f\n",i,goods[i].x);}}int main(){int j=1,n,i;float M;while(j)system("cls");printf("输入物品的总数:");scanf("%d",&n);struct goodinfo goods[n+1];//动态定义结构体数组的大小printf("背包最大容量:");scanf("%f",&M);for(i=1;i<=n;i++){goods[i].flag=i;printf("weight input:");scanf("%f",&goods[i].w);printf("price input:");scanf("%f",&goods[i].p);goods[i].p/=goods[i].w;}Insertionsort(goods,n);bag(goods,M,n);printf("press <1> to run again\npress <0> to exit\n请输入操作码:");scanf("%d",&j);}return 0; }。

贪心算法之背包问题

贪心算法之背包问题

贪⼼算法之背包问题贪⼼算法(⼜称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

贪⼼算法不是对所有问题都能得到整体最优解,关键是贪⼼策略的选择,选择的贪⼼策略必须具备⽆后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

完全背包问题:给定n个物品和⼀个容量为C的背包,物品i的重量是Wi,其价值为Vi,背包问题是如何选择⼊背包的物品,使得装⼊背包的物品的总价值最⼤,与0-1背包的区别是,在完全背包问题中,可以将物品的⼀部分装⼊背包,但不能重复装⼊。

设计算法的思路很简单,计算物品的单位价值,然后尽可能多的将单位重量价值⾼的物品放⼊背包中。

python实现代码如下:1# coding=gbk2# 完全背包问题,贪⼼算法3import time4__author__ = 'ice'567class goods:8def__init__(self, goods_id, weight=0, value=0):9 self.id = goods_id10 self.weight = weight11 self.value = value121314# 不适⽤于0-1背包15def knapsack(capacity=0, goods_set=[]):16# 按单位价值量排序17 goods_set.sort(key=lambda obj: obj.value / obj.weight, reverse=True)18 result = []19for a_goods in goods_set:20if capacity < a_goods.weight:21break22 result.append(a_goods)23 capacity -= a_goods.weight24if len(result) < len(goods_set) and capacity != 0:25 result.append(goods(a_goods.id, capacity, a_goods.value * capacity / a_goods.weight))26return result272829 some_goods = [goods(0, 2, 4), goods(1, 8, 6), goods(2, 5, 3), goods(3, 2, 8), goods(4, 1, 2)]3031 start_time = time.clock()32 res = knapsack(6, some_goods)33 end_time = time.clock()34print('花费时间:' + str(end_time - start_time))3536for obj in res:37print('物品编号:' + str(obj.id) + ' ,放⼊重量:' + str(obj.weight) + ',放⼊的价值:' + str(obj.value), end=',')38print('单位价值量为:' + str(obj.value / obj.weight))394041# 花费时间:2.2807240614677942e-0542# 物品编号:3 ,放⼊重量:2,放⼊的价值:8,单位价值量为:4.043# 物品编号:0 ,放⼊重量:2,放⼊的价值:4,单位价值量为:2.044# 物品编号:4 ,放⼊重量:1,放⼊的价值:2,单位价值量为:2.045# 物品编号:1 ,放⼊重量:1,放⼊的价值:0.75,单位价值量为:0.75。

列举用贪心算法求解的经典问题

列举用贪心算法求解的经典问题

列举用贪心算法求解的经典问题
1. 零钱兑换问题:给定一些面值不同的硬币和一个金额,要求用最少的硬币凑出这个金额。

2. 最小生成树问题:给定一个无向带权图,要求用最小的权值构建一棵生成树。

3. 背包问题:给定一些物品和一个背包,每个物品有对应的价值和重量,要求在背包容量限制下,选取物品使得总价值最大。

4. 活动安排问题:有若干个活动需要分配一段时间,每个活动有对应的开始时间和结束时间,要求选取尽可能多的活动,使得任两个安排的活动时间不重叠。

5. 单源最短路径问题:给定一个有向带权图和一个起始节点,要求求出从起始节点到其他所有节点的最短路径。

6. 任务调度问题:有若干个需要完成的任务和多个可执行任务的处理器,要求将任务分配给处理器,使得执行总时间最小。

7. 区间覆盖问题:给定一些区间,要求用尽可能少的区间覆盖整个线段。

8. 哈夫曼编码问题:给定一些字符及其对应的出现概率,要求用最短的编码方式表示这些字符。

贪心算法经典问题:活动安排,背包问题,最优装载,单源最短路径 Dijiksra,找零钱问题,多机调度

贪心算法经典问题:活动安排,背包问题,最优装载,单源最短路径 Dijiksra,找零钱问题,多机调度
{if (s[i]>=f[j]) { a[i]=true;j=i;count++;}
else a[i]=false;
}
return count;
}
背包问题
void Knapsack(int n,float M,float v[],float w[],float x[])
{Sort(n,v,w);//以每种物品单位重量的价值Vi/Wi从大到小排序
for(int i= 1;i<=n; i++)
{dist[i]=c[v][i]; s[i]=false;
if(dist[i]==maxint) prev[i]=0;
else prev[i]=v;
}
dist[v]=0 ; s[v]=true;
for(int i=1;i<n;i++)
{int temp = maxint, u = v;
if(newdist<dist[j]) {dist[j]= newdist;prev[j]=u; }
}
}//ENDFOR
}//END
找零钱问题
#define NUM4
void main()
{int m[NUM]={25,10,5,1};
int n;//假设n=99
cin>>n;
cout<<n<<"的找钱方案为:";
int max(int t[],int num);
int min(int t[],int m);
int set_work2(int t[],int n);
static int time[N]={2,8,18,32,50,72,98,128,182,200},s[M]={0,0,0};

贪心法求解背包问题

贪心法求解背包问题
贪心法求解背包问题
问题描述

已知有n种物品和一个可容纳M重量的背包,每种物品i的重 量为。假定将物品i的一部分放入背包就会得到的效益,这里,, 。显 然,由于背包容量是M,因此,要求所有选中要装入背包的物品总重 量不得超过M.。如果这n件物品的总重量不超过M,则把所有物品装 入背包自然获得最大效益。现需解决的问题是,在这些物品重量的和 大于M的情况下,该如何装包,使得得到更大的效益值。由以上叙述, 可将这个问题形式表述如下: p i xi • 极 大 化目标函数 1i n • 约束条件 wi xi M • 1i n
0 xi 1, pi 0, wi 0,1 i n
算法分析

首先需确定最优的量度标准。这里考虑三种策略: • 策略1:按物品价值p降序装包, • 策略2:按物品重w升序装包 • 策略3:按物品价值与重量比值p/w的降序装包 分别以上面三种策略分别求以下情况背包问题的解: • n=7,M=15, 7 • ( p1 ,, p) =(10,5,15,7,6,18,3) • ( w1 ,, w7)=(2,3,5,7,1,4,1)
结果
The end,thank you!
请提问!
与其他算法比较
• 1.贪心法:处理问题的速度快,思想简单。使用该方法的 必要条件是寻找好的贪心法则。不足之处在于很多时候它 只能求的似优解,却不能求的最优解 • 2.动态规划法:可以求解最优解,重点在于徐兆最优决策 序列但是速度较慢。 • 3.分支限界法:可以求解最优解,重点在于寻找限界值。 易求最优解,但是空间花费较高,效率不是很高。 • பைடு நூலகம்择哪一种算法,不仅要根据问题本身还需要考虑到其他 因素,例如时间复杂度,空间复杂度,易求解等等因素。

[C++]贪心算法之活动安排、背包问题

[C++]贪心算法之活动安排、背包问题

[C++]贪⼼算法之活动安排、背包问题⼀、贪⼼算法的基本思想 在求解过程中,依据某种贪⼼标准,从问题的初始状态出发,直接去求每⼀步的最优解,通过若⼲次的贪⼼选择,最终得出整个问题的最优解。

从贪⼼算法的定义可以看出,贪⼼算法不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,⽽由问题⾃⾝的特性决定了该题运⽤贪⼼算法可以得到最优解。

如果⼀个问题可以同时⽤⼏种⽅法解决,贪⼼算法应该是最好的选择之⼀。

⼆、贪⼼算法的基本要素 (1)最优⼦结构性质 (2)贪⼼选择性质(局部最优选择)三、贪⼼算法实例 1、活动安排 设有n个活动的集合 E = {1,2,…,n},其中每个活动都要求使⽤同⼀资源,如演讲会场等,⽽在同⼀时间内只有⼀个活动能使⽤这⼀资源。

每个活动 i 都有⼀个要求使⽤该资源的起始时间 s i和⼀个结束时间 f i,且 s i< f i。

如果选择了活动i,则它在半开时间区间 [s i ,f i ) 内占⽤资源。

若区间 [s i , f i )与区间 [s j, f j ) 不相交,则称活动i与活动j是相容的。

当 s i ≥ f j或 s j ≥ f i时,活动 i 与活动 j 相容。

活动安排问题就是在所给的活动集合中选出最⼤的相容活动⼦集合。

例如:1 #include <iostream>2 using namespace std;34 #define NUM 5056 void GreedySelector(int n, int s[], int f[], bool b[])7 {8 b[1]=true; //默认将第⼀个活动先安排9 int j=1; //记录最近⼀次加⼊b中的活动1011 //依次检查活动i是否与当前已选择的活动相容12 for(int i=2;i<=n;i++)13 {14 if (s[i]>=f[j])15 {16 b[i]=true;17 j=i;18 }19 else20 b[i]=false;21 }22 }2324 int main()25 {26 int s[] = {0,1,3,0,5,3,5,6,8,8,2,12}; //存储活动开始时间27 int f[] = {0,4,5,6,7,8,9,10,11,12,13,14}; //存储活动结束时间28 bool b[NUM]; //存储被安排的活动编号29 int n = (sizeof(s) / sizeof(s[0])) - 1;3031 GreedySelector(n, s, f, b);3233 for(int i = 1; i <= n; i++) //输出被安排的活动编号和它的开始时间和结束时间34 {35 if(b[i]) cout << "活动 " << i << " :" << "(" << s[i] << "," << f[i] << ")" <<endl;36 }37 return 0;38 } 2、背包问题 给定⼀个载重量为 M 的背包,考虑 n 个物品,其中第 i 个物品的重量 w i(1 ≤ i ≤ n),价值 v i(1 ≤ i ≤ n),要求把物品装满背包,且使背包内的物品价值最⼤。

贪心算法适用于哪些问题场景

贪心算法适用于哪些问题场景

贪心算法适用于哪些问题场景贪心算法是一种在求解问题时总是做出在当前看来是最好选择的算法。

虽然它不一定能得到全局最优解,但在许多特定的问题场景中,却能高效地给出一个较为满意的结果。

以下就来探讨一下贪心算法适用于哪些问题场景。

首先,贪心算法常用于活动安排问题。

假设有一系列活动,每个活动都有开始时间和结束时间。

我们需要在有限的时间内选择尽可能多的活动来参加。

此时,贪心算法的策略可以是每次都选择结束时间最早的活动。

因为这样能为后续可能的活动留出更多的时间,从而有可能安排更多的活动。

例如,有活动 A(开始时间 8:00,结束时间10:00)、B(开始时间 9:00,结束时间 11:00)、C(开始时间 10:30,结束时间 12:00)。

按照贪心算法,先选择 A 活动,然后由于 B 活动与 A 活动时间有冲突,不能选择,接着可以选择 C 活动。

这种情况下,通过贪心选择,能够安排两个活动。

其次,在找零钱问题中,贪心算法也能发挥作用。

比如,当我们需要用最少的硬币找给顾客零钱时,假设我们有 1 元、5 角、1 角的硬币,要找给顾客 17 元。

贪心算法会先尽量选择面值大的硬币,即先选择 1个 1 元硬币,然后选择 1 个 5 角硬币,再选择 2 个 1 角硬币,这样就能用最少的硬币数量找零。

再者,贪心算法在背包问题的某些变种中适用。

比如,在部分背包问题中,物品可以分割,每个物品都有一定的价值和重量。

我们要在背包容量有限的情况下,装入物品使得总价值最大。

此时,贪心算法可以按照物品的单位重量价值(价值/重量)从大到小的顺序来选择装入背包的物品。

例如,有物品 A(价值 100,重量 20)、物品 B(价值 60,重量 10)、物品 C(价值 80,重量 15),背包容量为 25。

按照贪心算法,先计算单位重量价值,A 为 5,B 为 6,C 为 533。

所以先选择 B 物品全部装入,然后选择 C 物品部分装入(10 重量),这样就能使背包内物品的总价值最大。

单源最短路径贪心算法

单源最短路径贪心算法

单源最短路径贪心算法贪心算法是一种常见的解决最短路径问题的方法。

它通常基于贪心选择性质,每一步都选择当前最优解。

然而,对于单源最短路径问题,贪心算法并不是最优的解决方案,因为它无法保证在每一步都选择最优解的情况下,最终得到的路径一定是最短的。

尽管如此,贪心算法仍然具有一定的实用价值,并且可以作为其他更高效算法的基础。

Dijkstra算法是一种常见的基于贪心策略的单源最短路径算法。

它以一个起点为基准,通过逐步改善路径长度的估计值来找到最短路径。

Dijkstra算法的基本思想是,首先将起点标记为已访问,并将其到起点的距离设为0。

然后,从起点开始,逐步找到离起点最近的节点,并更新与它相邻的节点的距离。

具体步骤如下:1.初始化距离表和已经访问集合。

-距离表:记录每个节点到起点的当前最短距离,初始值为正无穷。

-已经访问集合:记录已经找到最短路径的节点。

2.将起点的距离设置为0,同时将起点加入已经访问集合。

3.重复以下步骤直到所有节点都被访问:a.从距离表中选取一个未被访问的节点,使其到起点的距离最小。

b.将该节点标记为已经访问,并更新与它相邻节点的距离。

c.如果更新后的距离比距离表中的距离小,则更新距离表。

4.返回距离表。

Dijkstra算法的时间复杂度为O(V^2),其中V表示图中的节点数。

该算法需要遍历所有节点,并更新距离表。

由于要选择最小的距离节点,因此需要进行一次线性,因此总体时间复杂度为O(V^2)。

然而,当图的规模较大时,Dijkstra算法的效率可能会较低。

为了提高算法的效率,可以使用优先队列(堆)来存储未被访问的节点,并选择距离最小的节点。

这样可以将时间复杂度降低为O((V+E)logV),其中E 表示图中的边数。

总结起来,贪心算法是一种解决单源最短路径问题的基本思想。

Dijkstra算法是贪心算法的一种常见应用,它通过逐步改善路径长度的估计值来找到最短路径。

尽管Dijkstra算法的时间复杂度较高,但可以通过使用优先队列来优化算法的效率。

背包问题贪心法和动态规划方案法求解

背包问题贪心法和动态规划方案法求解

背包问题贪心法和动态规划方案法求解嘿,大家好!今天咱们来聊聊那个让人又爱又恨的背包问题。

这个问题可是算法领域的经典难题,不过别怕,今天我会用贪心法和动态规划两种方法帮你轻松搞定它!来个简单直接的背景介绍。

背包问题,简单来说,就是给定一组物品,每个物品都有一定的价值和重量,你需要在不超过背包承载重量的前提下,挑选出价值最大的物品组合。

听起来是不是有点像生活中的购物决策?哈哈,没错,这就是背包问题的魅力所在。

好,下面咱们直接进入主题。

一、贪心法贪心法,顾名思义,就是每一步都选择当前看起来最优的方案。

对于背包问题,贪心法的核心思想就是:每次都选取价值密度最大的物品。

1.计算每个物品的价值密度,即价值除以重量。

2.然后,按照价值密度从大到小排序。

3.从排序后的列表中依次选取物品,直到背包装满或者没有物品可选。

二、动态规划法动态规划,这是一种更加严谨、也更复杂的方法。

它的核心思想是:通过把大问题分解成小问题,逐步求解,最终得到最优解。

1.定义一个二维数组dp[i][j],表示在前i个物品中选择,背包容量为j时的最大价值。

2.我们考虑第i个物品是否放入背包。

如果放入,则前i-1个物品在容量为j-w[i]时的最大价值加上w[i]的价值,即dp[i][j]=dp[i-1][j-w[i]]+w[i]。

如果不放入,则前i-1个物品在容量为j时的最大价值,即dp[i][j]=dp[i-1][j]。

3.通过比较这两种情况,取最大值作为dp[i][j]的值。

整个过程中,我们需要遍历所有物品和所有可能的背包容量,最终得到dp[n][W]就是我们要找的最大价值。

现在,让我们用一段代码来具体实现一下动态规划法:defknapsack(W,weights,values):n=len(values)dp=[[0for_inrange(W+1)]for_inrange(n+1)]foriinrange(1,n+1):forjinrange(1,W+1):ifj>=weights[i-1]:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weights[i-1]]+values[i -1])else:dp[i][j]=dp[i-1][j]returndp[n][W]测试数据W=50weights=[10,20,30]values=[60,100,120]print(knapsack(W,weights,values))怎么样?是不是觉得动态规划法虽然复杂,但逻辑清晰,更容易找到最优解?通过上面的分析,我们可以看到,贪心法简单高效,但有时候并不能得到最优解;而动态规划法虽然计算复杂度较高,但可以得到最优解。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

活动安排
public static int greedySelector(int [] s, int [] f, boolean a[])
{ //s[]开始时间f[]结束时间
int n=s.length-1;
a[1]=true;
int j=1;
int count=1;
for (int i=2;i<=n;i++)
{ if (s[i]>=f[j]) { a[i]=true; j=i; count++; }
else a[i]=false;
}
return count;
}
背包问题
void Knapsack(int n,float M,float v[],float w[],float x[])
{ Sort(n,v,w); //以每种物品单位重量的价值Vi/Wi从大到小排序
int i;
for (i=1;i<=n;i++) x[i]=0;
float c=M;
for (i=1;i<=n;i++)
{ if (w[i]>c) break;
x[i]=1;
c-=w[i];
}
if (i<=n) x[i]=c/w[i]; //允许放入一个物品的一部分
}
最优装载
void Loading(int x[], T ype w[], T ype c, int n)
{ int *t = new int [n+1]; //t[i]要存的是w[j]中重量从小到大的数组下标Sort(w, t, n); //按货箱重量排序
for (int i = 1; i <= n; i++) x[i] = 0; //O(n)
for (int i = 1; i <= n && w[t[i]] <= c; i++)
{x[t[i]] = 1; c -= w[t[i]];} //调整剩余空间
}
单源最短路径Dijiksra
template<class Type>
void Dijikstra(int n, int v, Type dist[], int prev[], Type **c)
{ //c[i][j]表示边(i,j)的权,dist[i]表示当前从源到顶点i的最短特殊路径bool s[maxint];
for(int i= 1;i<=n; i++)
{ dist[i]=c[v][i]; s[i]=false;
if(dist[i]==maxint) prev[i]=0;
else prev[i]=v;
}
dist[v]=0 ; s[v]=true;
for(int i=1;i<n;i++)
{ int temp = maxint, u = v;
for(int j= 1;j<=n; j++)
if( (!s[j])&&(dist[j]<temp) ){u= j ; temp=dist[j]; }s[u]= true;
for(int j= 1;j<=n;j++)
if( (!s[j])&&(c[u][j])<maxint)
{ Type newdist = dist[u]+c[u][j];
if(newdist<dist[j]) {dist[j]= newdist; prev[j]=u; } }
}//ENDFOR
}//END
找零钱问题
#define NUM 4
void main()
{ int m[NUM]={25,10,5,1};
int n; //假设n=99
cin>>n;
cout<<n<<"的找钱方案为:";
for(int i=0;i<NUM;i++)
while(n>=m[i]&&n>0)
{cout<<m[i]<<" ";
n-=m[i];
}
}//END
多机调度
#define N 10
#define M 3
void sort(int t[],int n);
int set_work1(int t[],int n);
int max(int t[],int num);
int min(int t[],int m);
int set_work2(int t[],int n);
static int time[N]={2,8,18,32,50,72,98,128,182,200},s[M]={0,0,0};
void main()
{sort(time,N);
if(M>=N) //作业数小于机器数
cout<<set_work1(time,N)<<endl;
else
cout<<set_work2(time,N)<<endl;
}
void sort(int t[],int n)
{for(int k=0;k<n-1;k++) //用选择法将处理时间从大到小排序{int j=k;
for (int i=k; i<n; i++)
if (t[i]>t[j]) j=i;
{int temp=t[j];t[j]=t[k];t[k]=temp;}
}
}
int max(int t[],int num) //max函数求解处理时间总和最长{int max=t[0];
for(int i=1;i<num;i++)
if(max<t[i]) max=t[i];
return max;
}
int min(int t[],int m)
{int min=0; //min记录目前处理作业时间和最小的机器号for(int i=1;i<m;i++)
if(s[min]>s[i]) min=i;
return min;
}
int set_work1(int t[],int n)
{ int m=0;
for(int i=0;i<n;i++) //分派作业
s[m++]+=t[i];
return max(s,N);
}
int set_work2(int t[],int n)
{ for(int i=0;i<n;i++)
s[min(s,M)]+=t[i];
return max(s,M);
}。

相关文档
最新文档