贪心算法——算法总结(一)

本文深入探讨贪心算法的基本概念、优缺点及实际应用。通过一个具体示例,展示贪心算法如何在资源分配问题中找到高效解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

贪心算法在几个基本算法里面算是相对简单的算法了,思路也是非常简单的,每一步总是做出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。基本思路就是从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到某算法中的某一步不能再继续前进时,算法停止。


对于这个比较简单的算法,我们就先了解一下他的利弊吧,利当然就是简单,省时,好用。下面我们看看贪心法存在的一些问题。


贪心法存在的问题:
1. 不能保证求得的最后解是最佳的;
2. 不能用来求最大或最小解问题;
3. 只能求满足某些约束条件的可行解的范围


上述的这些问题可以在其他算法里面得到相应的解决,请继续关注我的博客,但是我们也不会因此放弃对贪心算法的使用。这正是敏捷开发所提倡的,永远没有最好的,只有最适合的.我们选用贪心算法的原因就是因为他能够满足当前的需要并且比其他算法更加简单。


下面请看示例题:

有N个商品,每个商品的重量为WI,价格为:PI,现有一个背包,最多能装M的重量.其中(0<=I<N,0<wi<M)。问:怎样装能使包中装入的商品价值最高(对于每个商品可以只装该商品的一部分)

代码如下:

#include<stdio.h>

//参数:n表示是背包可以存放物品的种类
//参数:指针p指向的数组是存放物品价值的数组
//参数:指针q指向的数组是存放物品重量的数组
static void sort(int n,float *p,float *q)
{
 int i;
 int j;
 for(i=0;i<n-1;i++)
 for(j=i+1;j<n;j++)
 if((*(p+i))/(*(q+i))<(*(p+j))/(*(q+j)))
 {
  float f;
  f=*(p+i);
  *(p+i)=*(p+j);
  *(p+j)=f;
  
  f=*(q+i);
  *(q+i)=*(q+j);
  *(q+j)=f;
 }
  
}
 

//参数:指针x指向的数组是存放物品的情况
//参数:m表示的是背包的容量
//参数:n表示的是背包可以存放物品的种类
static void knapsack(int n,float m,float *v,float *w,float *x)
{
 sort(n,v,w);
 int i;
 for(i=0;i<n;i++)
 {
  if(*(w+i)>m) 
   break;
  //可以存放该物品时,置1
  *(x+i)=1;
  //放入后,背包的容量减少
  m-=*(w+i);
 }
 //当此时背包的容量不够存放整个物品的情况时,存放一部分
 if(i<n)
  *(x+i)=m/(*(w+i));
 
}
 
int main()
{
 int n=6;//物品种类 
 int m=100;//背包容量
 float w1[6]={15,5,60,25,55,80};//各种物品的重量
 float v1[6]={20,30,30,10,55,40};//各种物品的价值
 float x1[6];//存放各种物品的存放情况
 float *x;
 float *w;
 float *v;
 w=w1;
 v=v1;
 x=x1;
 
 
 int i;
 
 for(i=0;i<n;i++)
 *(x+i)=0;
 
 knapsack(n,m,v1,w1,x);
 
 printf("\n===========输出物品容量数组内容======================\n");
 
 for(i=0;i<n;i++)
 printf("%.1f\t",*(w+i));
 
 printf("\n============输出物品价值数组内容=====================\n");
 
 for(i=0;i<n;i++)
 printf("%.1f\t",*(v+i));
 
 printf("\n============输出物品存放情况数组=====================\n");
 for(i=0;i<n;i++)
 printf("%.1f\t",*(x+i));
 
 printf("\n============END=====================\n");
 
return 0; 
}

简单的例子,说明贪心算法如何使用。贪心算法是非常简单的算法,就像在生活中,如果我们想给别人找38块钱的话,我们最先考虑的是先找一张20元,在找一张10元,在找一张5元和三张一元,而不会直接找38张一元,这就是一个典型的贪心算法。所以,生活中处处有算法,缺少发现的眼睛。

<think>好的,我需要帮用户理解贪心算法在装船问题中的应用和实现。首先,我得回忆装船问题的基本概念,以及贪心算法的原理。装船问题要求在不超过货船最大载重量的情况下,选择货物使得总价值最大。贪心算法在这里的应用通常是基于某种局部最优的选择,比如价重比。 根据用户提供的引用,问题描述是选择若干货物,使得总重量不超过M,而总价重比最大。这里的价重比指的是每单位重量的价值,即p_i/w_i。所以,贪心策略应该是优先选择价重比高的货物,直到载重量用完。 接下来,我需要整理实现步骤。首先计算每种货物的价重比,然后按照这个比例从高到低排序。排序后依次选取货物,直到无法再装下更多的货物。这里需要注意,可能需要部分装载某种货物,但根据引用中的输入描述,p_i是w_i的整数倍,可能意味着每种货物可以分割,或者必须整件装载?需要仔细看问题要求。 查看引用[4],输入描述中提到p_i是w_i的整数倍,这可能意味着货物可以按整数倍分割,比如如果选择部分重量,价值也按比例计算。但问题输出是整数,所以可能需要全部装载或者不装,但根据价重比的计算方式,可能允许部分装载。不过,根据代码示例中的做法,用户提供的引用[1]提到使用冒泡排序按价重比排序,然后选择货物直到载重用完,可能这里的货物是可以分割的,即可以取部分重量,这样总价值就是按照价重比计算的。比如,如果剩余载重不足以装下全部某货物,就装部分,此时价值为剩余载重乘以价重比。 然后,实现步骤包括计算价重比、排序、贪心选择。代码中的排序部分引用[1]指出冒泡排序效率低,建议改用快速排序,但装船问题中货物种固定为10种,所以冒泡排序可能足够,但作为般情况可能需要更高效的算法。 用户可能想知道具体的实现代码,但根据问题中的引用,代码示例中的结构可能涉及结构体存储货物信息,计算价重比,排序,然后遍历。例如,定义个货物结构体,包含p、w、c(价重比),然后排序,再累加。 需要注意的问题包括排序的正确性,如何处理剩余载重,以及是否允许部分装载。根据引用中的问题描述,输出是最大价值,而输入中的p_i是w_i的整数倍,可能允许部分装载,但需要确认。例如,若货物A有w=2吨,p=4,价重比2。如果剩余载重为1吨,那么可以装0.5个货物A,得到价值1吨×2=2。但根据输入p_i是w_i的整数倍,这样分割后价值可能还是整数。 在代码实现中,引用[1]提到使用冒泡排序,但可以优化为快速排序。因此,在示例代码中,可能使用快速排序来提高效率,尤其是当货物种较多时。 总结回答的结构应该是:问题描述、贪心策略(按价重比排序)、实现步骤、代码示例、优化建议、应用场景,以及潜在问题和注意事项。同时,生成相关问题,如其他算法对比、时间复杂度和处理不可分割货物的情况等。 需要确保所有数学公式用$...$,比如价重比表示为$c_i = \frac{p_i}{w_i}$,独立公式用$$...$$。例如,总价值的计算公式可能需要单独成段。 最后,根据引用中的信息,正确添加引用标记,如引用[1]提到使用冒泡排序,可以将其放在对应段落末尾。同时,确保回答使用中文,代码语法正确,结构清晰。</think>### 贪心算法在装船问题中的实现应用 #### 、问题描述 装船问题要求从$N$种货物中挑选若干吨装入货轮,**总重量不超过$M$吨**,且**总价值最大化**。引用中明确说明,货物可分割(因$p_i$是$w_i$的整数倍),因此允许选择部分货物[^4]。 #### 二、贪心策略设计 贪心算法的核心是**价重比优先**,即优先选择$\text{价重比} = \frac{\text{价值}}{\text{重量}}$最高的货物。这策略的数学表示为: $$c_i = \frac{p_i}{w_i}$$ 通过按$c_i$降序排序,逐步装载直至载重$M$耗尽[^1]。 #### 三、实现步骤 1. **计算价重比**:遍历所有货物,计算$c_i = p_i / w_i$ 2. **排序**:按$c_i$从高到低对货物排序(冒泡排序或更优算法) 3. **贪心选择**:依次装载货物,若当前货物重量$\leq$剩余载重,则全装;否则装部分[^3] #### 四、代码实现(Python) ```python def load_ship(M, goods): # 计算价重比并排序 sorted_goods = sorted(goods, key=lambda x: x[0]/x[1], reverse=True) total_value = 0 remaining = M for p, w in sorted_goods: if remaining >= w: total_value += p remaining -= w else: total_value += (p / w) * remaining break # 载重已满 return int(total_value) # 因p_i是w_i整数倍,结果必为整数 # 示例输入:M=100, goods格式为[(p1, w1), (p2, w2), ...] print(load_ship(100, [(60, 10), (120, 30), (100, 20)])) # 输出:240 ``` #### 五、优化注意事项 1. **排序效率**:当$N$较大时,冒泡排序$O(n^2)$效率低,可改用快速排序$O(n \log n)$[^1] 2. **输入约束**:$p_i$是$w_i$的整数倍,确保部分装载时价值仍为整数 3. **空间优化**:无需存储完整结构体,直接使用元组排序 #### 六、应用场景 1. 物流运输中的**集装箱装载优化** 2. 资源分配问题(如云计算资源调度) 3. 背包问题的简化版本(可分割物品)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值