Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >你听过算法也是可以贪心的吗?

你听过算法也是可以贪心的吗?

作者头像
用户1332428
发布于 2018-03-08 10:38:08
发布于 2018-03-08 10:38:08
1.2K00
代码可运行
举报
文章被收录于专栏:人工智能LeadAI人工智能LeadAI
运行总次数:0
代码可运行
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

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

基本思路

1、建立数学模型来描述问题;

2、把求解的问题分成若干个子问题;

3、对每一子问题求解,得到子问题的局部最优解;

4、把子问题的解局部最优解合成原来解问题的一个解。

算法实现

1、从问题的某个初始解出发。

2、采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或规模。

3、将所有部分解综合起来,得到问题的最终解。

实例分析

实例1、背包问题

问题描述

有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。

问题分析

1、目标函数: ∑pi最大,使得装入背包中的所有物品pi的价值加起来最大。

2、约束条件:装入的物品总重量不超过背包容量:∑wi<=M( M=150)

3、贪心策略:

选择价值最大的物品

选择价值最大的物品

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

有三个物品A,B,C,其重量分别为{30,10,20},价值分别为{60,30,80},背包的容量为50,分别应用三种贪心策略装入背包的物品和获得的价值如下图所示:

三种策略

算法设计

1、计算出每个物品单位重量的价值

2、按单位价值从大到小将物品排序

3、根据背包当前所剩容量选取物品

4、如果背包的容量大于当前物品的重量,那么就将当前物品装进去。否则,那么就将当前物品舍去,然后跳出循环结束。

代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
#include<algorithm>
 using namespace std;
typedef struct{     
int w;     
int v;     
double avg;
 }P;
bool cmp(P a,P b){     
return a.avg>b.avg; } int main(){    
 P *p;     
int n,i,m;//n 物品个数 m背包容量     
while(cin>>n>>m){         
p=new P[n];         
for(i=0;i<n;i++){            
 cin>>p[i].w>>p[i].v;            
 p[i].avg=p[i].v/p[i].w*1.0;         
}         
sort(p,p+n,cmp);        
 int maxvalue=0;         
for(i=0;i<n;i++){             
if(p[i].w<=m){                 
m-=p[i].w;                 
maxvalue+=p[i].v;            
 }else{                 
break;            
 }         
 }         
cout<<maxvalue<<endl;    
 }    
 return 0;
}

运行结果

实例2、活动安排问题

问题描述

设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi 。要求设计程序,使得安排的活动最多。

(ps:活动结束时间按从小到大排序)

问题分析

活动安排问题要求安排一系列争用某一公共资源的活动。用贪心算法可提供一个简单、漂亮的方法,使尽可能多的活动能兼容的使用公共资源。设有n个活动的集合{0,1,2,…,n-1},其中每个活动都要求使用同一资源,如会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间starti和一个结束时间endi,且starti<endi。如选择了活动i,则它在半开时间区间[starti,endi)内占用资源。若区间[starti,endi)与区间[startj,endj)不相交,称活动i与活动j是相容的。也就是说,当startj≥endi或starti≥endj时,活动i与活动j相容。活动安排问题就是在所给的活动集合中选出最多的不相容活动。

活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子。该问题要求高效地安排一系列争用某一公共资源的活动。贪心算法提供了一个简单、漂亮的方法使得尽可能多的活动能兼容地使用公共资源。

算法设计

若被检查的活动i的开始时间starti小于最近选择的活动j的结束时间endj,则不选择活动i,否则选择活动i加入集合中。运用该算法解决活动安排问题的效率极高。当输入的活动已按结束时间的非减序排列,算法只需O(n)的时间安排n个活动,使最多的活动能相容地使用公共资源。如果所给出的活动未按非减序排列,可以用O(nlogn)的时间重排。

代码实现

代码1

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
#include<algorithm>
using namespace std;
struct actime{    
int start,finish;
}act[1002]; bool cmp(actime a,actime b)
{     
return a.finish<b.finish;
}
int main(){     int i,n,t,total;     
while(cin>>n){//活动的个数         
for(i=0;i<n;i++){             
cin>>act[i].start>>act[i].finish;         
}         
sort(act,act+n,cmp);//按活动结束时间从小到大排序        
 t=-1;         
total=0;         
for(i=0;i<n;i++){             
if(t<=act[i].start){                 
total++;                 
t=act[i].finish;            
 }         
}         
cout<<total<<endl;
 }     
return 0; 
}

运行结果1

代码2

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream> using namespace std; 
 template<class Type> void GreedySelector(int n, Type s[], Type f[], bool A[]);  
 const int N = 11;  int main() {     //下标从1开始,存储活动开始时间    
  int s[] = {0,1,3,0,5,3,5,6,8,8,2,12};      //下标从1开始,存储活动结束时间    
  int f[] = {0,4,5,6,7,8,9,10,11,12,13,14};      
  bool A[N+1];      
  cout<<"各活动的开始时间,结束时间分别为:"<<endl;     
  for(int i=1;i<=N;i++)     {         
  cout<<"["<<i<<"]:"<<"("<<s[i]<<","<<f[i]<<")"<<endl;     }     
  GreedySelector(N,s,f,A);     
  cout<<"最大相容活动子集为:"<<endl;     
  for(int i=1;i<=N;i++)     {         
  if(A[i]){             
  cout<<"["<<i<<"]:"<<"("<<s[i]<<","<<f[i]<<")"<<endl;         }     }     
   return 0; }  
   template<class Type> void GreedySelector(int n, Type s[], Type f[], bool A[]) {    
    A[1]=true;     int j=1;//记录最近一次加入A中的活动     
     for (int i=2;i<=n;i++)//依次检查活动i是否与当前已选择的活动相容 
         {         if (s[i]>=f[j])     
             {             A[i]=true;       
                   j=i;         }      
                      else         {        
                           A[i]=false;      
                              }     } }

运行结果2

实例3、最小生成树(克鲁斯卡尔算法)

问题描述

求一个连通无向图的最小生成树的代价(图边权值为正整数)。

输入

第一行是一个整数N(1<=N<=20),表示有多少个图需要计算。以下有N个图,第i图的第一行是一个整数M(1<=M<=50),表示图的顶点数,第i图的第2行至1+M行为一个M*M的二维矩阵,其元素ai,j表示图的i顶点和j顶点的连接情况,如果ai,j=0,表示i顶点和j顶点不相连;如果ai,j>0,表示i顶点和j顶点的连接权值。

输出

每个用例,用一行输出对应图的最小生成树的代价。

样例输入

1 6 0 6 1 5 0 0 6 0 5 0 3 0 1 5 0 5 6 4 5 0 5 0 0 2 0 3 6 0 0 6 0 0 4 2 6 0

样例输出

15

Kruskal算法简述

假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含 n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林。之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林中只有一棵树,也即子图中含有 n-1条边为止。

模拟过程:

模拟过程

算法难点:

(1)边的选择要求从小到大选择,则开始显然要对边进行升序排序。 (2)选择的边是否需要,则从判断该边加入后是否构成环入手。

算法设计

(1)对边升序排序 在此采用链式结构,通过插入排序完成。每一结点存放一条边的左右端点序号、权值及后继结点指针

(2)边的加入是否构成环 一开始假定各顶点分别为一组,其组号为端点序号。选择某边后,看其两个端点是否在同一组中,即所在组号是否相同,如果是,表示构成了环,则舍去。 如果两个端点所在的组不同,则表示可以加入,则将该边两端的组合并成同一组。

代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
using namespace std;
struct node
{
 int l;
 int r; 
 int len;
 node *next;
};
void insert(node *&h,node *p)   //指针插入排序
{
 node *q=h;
 while(q->next && q->next->len <= p->len)  {   q=q->next;  }  p->next=q->next;  q->next=p;
}
 int main() {
// freopen("001.in","r",stdin);
 node *h,*p;
 int n,m,x,temp;
 int *a;  int i,j;
 int sum;
 cin>>n;
 while(n--)
 {   
sum=0;   
cin>>m;   
a=new int[m+1];   
for (i=1;i<=m;i++)
  {    
a[i]=i;
  }   
h=new node;   
p=h;   
p->next=NULL;   
for (i=1;i<=m;i++)    
for (j=1;j<=m;j++)    
{     
cin>>x;    
 if (i>j && x!=0)    
 {      
p=new node;      
p->l=i;      
p->r=j;      
p->len=x;      
p->next=NULL;     
 insert(h,p);   //调用插入排序     
}   
 }           
p=h->next;    
while (p)    
{    
 if (a[p->l]!=a[p->r])    
 {      
 sum+=p->len;     
 temp=a[p->l];      
for(i=1;i<=m;i++)       
if (a[i]==temp)      
 {        
a[i]=a[p->r];       
}     
}   
 p=p->next;    
}    
/*   可以测试程序工作是否正常   
 p=h->next;    
while(p)    
{     
cout<<p->l<<':';cout<<p->r<<' ';     
cout<<p->le
n<<"   ";     
p=p->next;    
}    
*/    
cout<<sum<<endl;
 }
 return 0;
}

运行结果

实例4、hdu1050-Moving Tables

问题描述

在一个狭窄的走廊里将桌子从一个房间移动到另一个房间,走廊的宽度只能允许一个桌子通过。给出t,表示有t组测试数据。再给出n,表示要移动n个桌子。n下面有n行,每行两个数字,表示将桌子从a房间移到b房间。走廊的分布图如一图所示,每移动一个桌子到达目的地房间需要花10分钟,问移动n个桌子所需要的时间。

输入

3 4 10 20 30 40 50 60 70 80 2 1 3 2 200 3 10 100 20 80 30 50

输出

10 20 30

解题思路

若移动多个桌子时,所需要经过的走廊没有重合处,即可以同时移动。若有一段走廊有m个桌子都要经过,一次只能经过一个桌子,则需要m*10的时间移动桌子。 设一个数组,下标值即为房间号。桌子经过房间时,该房间号为下标对应的数组值即加10。最后找到最大的数组值,即为移动完桌子需要的最短时间。(以上为代码2,代码3同这个思想)

注意:

1、可能出发位置比目的地房间大,无论大小,我们都可以看做从小的房间移动到大的房间

2、出发房间为偶数则减一,结束房间为奇数则加一

我们首先输入每次移动的出发和结束房间,然后按每次移动的出发房间从小到大排序,然后直至所有的房间移动完毕。(代码1的解释)

代码1(我自己感觉不是贪心算法,属于暴力破解吧,大家酌情考虑)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
#include<algorithm>
 using namespace std;
 struct table{     
int from,to;     
bool flag;//记录改房间是否被访问过
}moving[205];
 bool cmp(table a,table b){     
return a.from<b.from;
}
 int main(){    
 int i,T,n;//T代表测试实例个数,n代表每个测试下的table个数     
cin>>T;     
while(T--){         
cin>>n;         
for(i=0;i<n;i++){             
cin>>moving[i].from>>moving[i].to;             
if(moving[i].from > moving[i].to)             
{                 
int temp = moving[i].from;                 
moving[i].from = moving[i].to;                
 moving[i].to = temp;             
}//可能出发位置比目的地房间大,无论大小,我们都可以看做从小的房间移动到大的房间             if(moving[i].from%2==0){//考虑实际情况,出发房间为偶数是减一,可参照题中给出的图一                 moving[i].from--;             
}             
if(moving[i].to%2==1){//考虑实际情况,结束房间为奇数是加一,                
 moving[i].to++;            
 }            
 moving[i].flag=false;//初始化房间未被访问过        
 }         
sort(moving,moving+n,cmp);//将所有table按出发房间从小到大排序;         
bool completion=false;//是否所有的table移动结束         
int cnt=-1,priorTo;//priorTo 记录前一个table移动结束的房间         
while(!completion){             
completion=true;             
cnt++;             
priorTo=0;             
for(i=0;i<n;i++){//每一轮将可以同时移动的table全部移动完:比如2->5,6->10,因为他们没有共用走廊                
 if(!moving[i].flag&&moving[i].from>priorTo){                     
moving[i].flag=true;//标记当前table已经移动完毕                     
priorTo=moving[i].to;                     
completion=false;                
 }             
}         
}     
cout<<cnt*10<<endl;    
 }     
return 0;
 }

代码1运行结果

代码2

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<cstdio>
#include<cstring>
 #include<algorithm>
using namespace std;
 int main()
{    
 int t,n,count[410],i,start,end,k;     
scanf("%d",&t);     
while(t--)     
{         
scanf("%d",&n);         
memset(count,0,sizeof(count));         
while(n--)         
{             
scanf("%d%d",&start,&end);             
if(start>end)//可能出发位置比目的地房间大。             
{            //无论大小,我们都可以看做从小的房间移动到大的房间                 
k=start;                 
start=end;                 
end=k;            
 }             
if(start%2==0)//考虑实际情况,出发房间为偶数是减一,可参照题中给出的图一                
start-=1;            
 if(end%2==1)//目的地房间为奇数时加一                
end+=1;             
for(i=start;i<=end;++i)                
count[i]+=10;         }         
printf("%d\n",*max_element(count,count+400));//STL中寻找数列最大值函数     
}    
 return 0;
 }

代码3

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <algorithm>
#include <cstring>
#define MAXN 500
using namespace std;
struct temp{     
int be,en;
};
bool comp(temp a,temp b){     
return a.be<b.be;
 }
int main(){     
temp my[MAXN];     
int m,n,i;     
cin>>m;    
 while(m--){         
cin>>n;         
i=0;         
int a,b,j;         
while(i<n){             
cin>>a>>b;             
if(a>b)a^=b^=a^=b;             
my[i].be=(a+1)/2;             
my[i++].en=(b+1)/2;        
 }         
sort(my,my+n,comp);         
int s=0,out=n,t=0;         
int aa[203];         
memset(aa,0,sizeof(aa));        
for(i=0;i<n;++i){             
for(j=my[i].be;j<=my[i].en;++j)aa[j]++;        
}        
sort(aa,aa+200);         
cout<<aa[199]*10<<'\12';     
}    
 return 0;
 }

参考

1、0021算法笔记——【贪心算法】贪心算法与活动安排问题(http://blog.csdn.net/liufeng_king/article/details/8709005)

2、C++最小生成树问题(http://blog.csdn.net/pukuimin1226/article/details/6440714)

3、C++c语言贪心算法(https://wenku.baidu.com/view/8e5f335b77232f60ddcca144.html)

4、HDOJ 1050 Moving Tables(经典贪心)(https://www.2cto.com/kf/201508/434067.html)

5、贪心算法——Hdu 1050 Moving Tables(http://blog.csdn.net/code_pang/article/details/8251240)

6、HDU Moving Tables (贪心)(http://blog.csdn.net/zp___waj/article/details/46494865)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-11-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 人工智能LeadAI 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
零基础学贪心算法
本文在写作过程中参考了大量资料,不能一一列举,还请见谅。 贪心算法的定义: 贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。 解题的一般步骤是: 1.建立数学模型来描述问题; 2.把求解的问题分成若干个子问题; 3.对每一子问题求解,得到子问题的局部最优解; 4.把子问题的局部最
Angel_Kitty
2018/04/08
1K0
零基础学贪心算法
疯子的算法总结(四)贪心算法
解决最优化问题的算法一般包含一系列的步骤,每一步都有若干的选择。对于很多最优化问题,只需要采用简单的贪心算法就可以解决,而不需要采用动态规划方法。贪心算法使所做的局部选择看起来都是当前最佳的,通过局部的最优化选择来产生全局最优解。本文将介绍贪心算法的理论基础和一些简单应用。在求最优解问题的过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。
风骨散人Chiam
2020/10/28
8100
疯子的算法总结(四)贪心算法
算法笔记(0002) - 【贪心算法】活动安排问题
在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
量子态的沐子呓
2019/12/25
1.3K0
算法笔记(0002) - 【贪心算法】活动安排问题
【算法分析】贪心法详解+范例+习题解答
顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。希望贪心算法得到的最终结果是整体最优的。贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。 在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。
司六米希
2022/11/15
1.2K0
【算法分析】贪心法详解+范例+习题解答
你必须知道的基础算法
对于贪心算法,我们要先将问题简化,然后依据贪心算法的理念,例如可以一起进行的事情,让他们一起进行。可以用一个条件完成的,就用一个条件完成。贪心算法就像人的贪心理念一样,先将可以贪的贪干净,然后在考虑特殊的情况,这样可以很好地进行代码的编写。
洋仔聊编程
2019/01/15
7730
ACM之贪心算法
所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最优解。也就是说,不 从整体最优上加以考虑,它所做出的仅仅是在某种意义上的局部最优解。 贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是, 贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性 (即某个状态以后的过程不会影响以前的状态,只与当前状态有关。) 所以,对所采用的贪心策略一定要仔细分析其是否满足无后效性。
Tanger
2021/06/16
7941
【地铁上的面试题】--基础部分--数据结构与算法--动态规划和贪心算法
动态规划是一种解决多阶段决策问题的算法思想,它通过将问题划分为若干个子问题,并保存子问题的解来求解原问题的方法。动态规划的特点包括以下几个方面:
喵叔
2023/07/09
4540
浅析C语言贪心算法
贪心算法的定义: 贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。 解题的一般步骤是: 1.建立数学模型来描述问题; 2.把求解的问题分成若干个子问题; 3.对每一子问题求解,得到子问题的局部最优解; 4.把子问题的局部最优解合成原来问题的一个解。 如果大家比较了解动态规划,就会发现它们之间的相似之处。最优解问题大部分都可以拆分成一个个的子问题,把解空间的遍历视作对子问题树的遍历,则以某种形式对树整个的遍历一遍就可以求出最优解,大部分情况下这是不可行的。贪心算法和动态规划本质上是对子问题树的一种修剪,两种算法要求问题都具有的一个性质就是子问题最优性(组成最优解的每一个子问题的解,对于这个子问题本身肯定也是最优的)。动态规划方法代表了这一类问题的一般解法,我们自底向上构造子问题的解,对每一个子树的根,求出下面每一个叶子的值,并且以其中的最优值作为自身的值,其它的值舍弃。而贪心算法是动态规划方法的一个特例,可以证明每一个子树的根的值不取决于下面叶子的值,而只取决于当前问题的状况。换句话说,不需要知道一个节点所有子树的情况,就可以求出这个节点的值。由于贪心算法的这个特性,它对解空间树的遍历不需要自底向上,而只需要自根开始,选择最优的路,一直走到底就可以了。
用户11036582
2024/03/21
2300
浅析C语言贪心算法
贪心算法及几个经典例子c语言_贪心算法一定是最优解吗
所谓贪心算法是指,在对问题求解时,总是做出在 当前看来是最好的选择 。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的 局部最优解 。
全栈程序员站长
2022/11/19
1.1K0
“365算法每日学计划”:03打卡-贪心算法
自从开始做公众号开始,就一直在思考,怎么把算法的训练做好,因为思海同学在算法这方面的掌握确实还不够。因此,我现在想做一个“365算法每日学计划”。
好好学java
2018/06/16
8040
“365算法每日学计划”:03打卡-贪心算法
如何通过贪心算法实现最优装载问题的高效解决
开始之前推荐一篇实用的文章:《对象池 GenericObjectPool 配置参数详解》,作者:【huazie】。
Lion 莱恩呀
2024/11/25
2620
如何通过贪心算法实现最优装载问题的高效解决
活动安排问题--贪心算法
活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子。该问题要求高效地安排一系列争用某一公共资源的活动。贪心算法提供了一个简单、漂亮的方法使得尽可能多的活动能兼容地使用公共资源。   设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi 。如果选择了活动i,则它在半开时间区间[si, fi]内占用资源。若区
用户1154259
2018/01/17
2.8K0
贪心算法(Java)
顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路径问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。
WHYBIGDATA
2023/01/31
6000
贪心算法(Java)
【算法/训练】:贪心(算法 & 题目训练)
在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
IsLand1314
2024/10/22
1670
【算法/训练】:贪心(算法 & 题目训练)
前端也能学算法:由浅入深讲解贪心算法
贪心算法是一种很常见的算法思想,而且很好理解,因为它符合人们一般的思维习惯。下面我们由浅入深的来讲讲贪心算法。
蒋鹏飞
2020/10/15
5290
前端也能学算法:由浅入深讲解贪心算法
贪心算法
贪心算法(Greedy Algorithm) 简介贪心算法,又名贪婪法,是寻找最优解问题的常用方法,这种方法模式一般将求解过程分成若干个步骤,但每个步骤都应用贪心原则,选取当前状态下最好/最优的选择(局部最有利的选择),并以此希望最后堆叠出的结果也是最好/最优的解。{看着这个名字,贪心,贪婪这两字的内在含义最为关键。这就好像一个贪婪的人,他事事都想要眼前看到最好的那个,看不到长远的东西,也不为最终的结果和将来着想,贪图眼前局部的利益最大化,有点走一步看一步的感觉。}
233333
2020/02/12
1K0
【愚公系列】2023年12月 五大常用算法(四)-贪心算法
贪心算法(Greedy Algorithm)的基本思想是,在每一步中都选择局部最优的解,最终得到全局最优解。也就是说,贪心算法是在一定的约束条件下,逐步地构建问题的解,通过每一步选择局部最优的策略来达到全局最优的解。贪心算法的求解过程非常高效,但有时可能会得到次优解或者无解。因此,在应用贪心算法时,需要注意问题的约束条件和性质,以及选取合适的贪心策略。
愚公搬代码
2023/12/15
2990
贪心算法和动态规划
贪心算法和动态规划是两种非常强大的算法设计策略,它们在许多复杂问题中都展现出了出色的性能。在计算机科学中,它们被广泛应用于解决优化问题,如资源分配、路径寻找等。在这篇博客中,我们将通过具体的Java案例来探讨这两种算法的设计和应用,并详细比较它们的区别。
人不走空
2024/02/20
2730
算法修炼之筑基篇——筑基二层后期(初步理解解决贪心算法)
贪心算法适用于一些具有贪心选择性质的问题,这些问题的最优解可以通过一系列局部最优解来达到。通常情况下,贪心算法的效率较高,因为它不需要进行全局搜索,而是通过局部选择来逐步构建解决方案。
命运之光
2024/03/20
1140
算法修炼之筑基篇——筑基二层后期(初步理解解决贪心算法)
大学课程 | 《算法分析与设计》笔记
程序与算法的区别:程序可以不满足算法的第四点性质即有限性。例如操作系统,是在无限循环中执行的程序。
Justlovesmile
2021/12/14
1.1K0
相关推荐
零基础学贪心算法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验