算法设计初步之贪心算法

简介: 算法设计初步之贪心算法

理论知识


贪心算法是指是这样一种方法,分步骤实施,它在每一步仅作出当时看起来最佳的选择,即局部最优的选择,希望这样的选择能导致全局最优解。在贪心算法的每一步所做的局部最优选择就叫做贪心选择。

其中贪心算法中贪心选择性质和最优子结构性是两个关键要素!

贪心选择性质:即是可以通过贪心选择来构造全局最优解

最优子结构性质上文已述。

贪心求解一般有下面几个步骤

做出贪心选择,用反证法假设当前步骤不是最优,推出矛盾,得到其是最优;再用数学归纳法证明其全局最优。

这里证明比较复杂,算是一个难点。


动态规划和贪心算法都能解决一些最优性问题,那么二者异同在哪?

基本上能用贪心也就能用动态规划,二者应用的问题都具有最优子结构,如果说动态规划是在所有子问题最优解的基础上推出更大的子问题的最优解直到得到答案,那么贪心就省略了所有子问题这个过程,它是做出一个选着再求解剩下的那个子问题,自顶向下。


一、活动选择


问题描述

假定有一个n个活动的集合S={a1,a2,…,an},这些活动都要求使用同一资源(如演讲会场),而这个资源在某个时刻只能供一个活动使用。每个活动ai都有一个开始时间si和一个结束时间fi,且0≤si


这个问题是典型的区间贪心问题

贪心选择:如果我们把各个活动按照结束时间排序,要求最大兼容集合,我们总是想着在兼容条件内选择最早结束的时间

证明:略

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000;
 struct node{
  int x,y; //定义活动结构体,x,y分别代表起始时间 
  bool operator <(const node &a)const{
  return y<a.y;
  }
 }a[maxn];
int main(){
  int n;scanf("%d",&n);
  for(int i=0;i<n;i++)
  scanf("%d%d",&a[i].x,&a[i].y);
  sort(a,a+n) ;//将其结束时间排序
  int sum=0,end;
  if(n) {  
  sum=1;end=a[0].y; //第一次贪心选择 
  }
  for(int i=1;i<n;i++) //贪心选择到结束 
  if(a[i].x>=end){
  sum++;
  end=a[i].y;
  }
  printf("%d",sum);
  return 0;
}


一个结果:

1685018274338.jpg


二、Huffman编码


数据结构里老生常谈的问题

贪心选择:每次选择待选集合中最小两个做叶子节点,其和为根结点加入待选集合。


代码思路:有n个结点,最后和就n-1个,可以用一个2n-1大的结构数组来构造Huffman树,用一个优先队列来存放集合

#include<iostream> 
#include<queue>
#include<string>
using namespace std;
#define N 1000
struct node{   //哈夫曼树的结构,采用静态二叉树 
  int weight;
  int parent;
  int lchild,rchild; 
} Node[N]; //定义一个足够大的静态哈夫曼树 
struct cmp{   //将优先队列按从小到大排列的比较函数 
  bool operator ()(int a,int b){
  return Node[a].weight>Node[b].weight; 
  }
};
priority_queue<int,vector<int>,cmp>q;
//弄成int型方便修改Node里的值 
string s[100];
void createhuff(int n){  //创建哈夫曼树 
  for(int i=1;i<=n;i++)
q.push(i);
int i,j,m=n+1;
while(q.size()>1){
  i=q.top();q.pop();
  j=q.top();q.pop();
  Node[m].weight=Node[i].weight+Node[j].weight;
  Node[m].lchild=i;Node[m].rchild=j;
  Node[i].parent=Node[j].parent=m;
  q.push(m++);
} 
}
void preorder(int root){  //前序遍历 
  if(root==0)
  return;
  printf("%d ",Node[root].weight);
  preorder(Node[root].lchild);
  preorder(Node[root].rchild);
}
void encodehuff (int n) {//生成编码,从下往上 
  for(int i=1;i<=n;i++){
  int p=Node[i].parent,k=i;
  string str;
  while(p){
    if(Node[p].lchild==k){ //这里生成的是逆向代码 
    str+="1";}
    else {
    str+="0";}  
    k=p;
    p=Node[k].parent;
  }
  for(int f=str.length();f>0;f--) //将其编码正向 
  s[i]+=str[f-1];
  }
}
void  printfcode(int n) {
  for(int i=1;i<=n;i++) 
  printf("%s\n",s[i].c_str());
  //这里用printf输出字符串需要将它转化为字符数组,用cout不用 
}
int main(){
  int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){  //从1开始,0值与空对应 
  scanf("%d",&Node[i].weight);
  Node[i].parent=Node[i].lchild=Node[i].rchild=0;
}
createhuff(n);
encodehuff(n);
printfcode(n);
return 0;
}


此外还有最小生成树问题、Dijkstra 算法等也应用了贪心算法稍后再论。


相关文章
|
29天前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
41 2
|
6月前
|
算法 C++ Python
数据结构与算法===贪心算法
数据结构与算法===贪心算法
|
2月前
|
算法 Java C++
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
|
3月前
|
算法 前端开发
一文了解贪心算法和回溯算法在前端中的应用
该文章深入讲解了贪心算法与回溯算法的原理及其在前端开发中的具体应用,并通过分析LeetCode题目来展示这两种算法的解题思路与实现方法。
|
4月前
|
算法
【算法】贪心算法——柠檬水找零
【算法】贪心算法——柠檬水找零
|
4月前
|
算法
【算法】贪心算法简介
【算法】贪心算法简介
|
5月前
|
算法 Python
Python算法高手进阶指南:分治法、贪心算法、动态规划,掌握它们,算法难题迎刃而解!
【7月更文挑战第10天】探索Python算法的精华:分治法(如归并排序)、贪心策略(如找零钱问题)和动态规划(解复杂问题)。通过示例代码揭示它们如何优化问题解决,提升编程技能。掌握这些策略,攀登技术巅峰。
135 2
|
5月前
|
存储 算法 Python
Python算法界的秘密武器:分治法巧解难题,贪心算法快速决策,动态规划优化未来!
【7月更文挑战第9天】Python中的分治、贪心和动态规划是三大关键算法。分治法将大问题分解为小问题求解,如归并排序;贪心算法每步选局部最优解,不保证全局最优,如找零钱;动态规划存储子问题解求全局最优,如斐波那契数列。选择合适算法能提升编程效率。
71 1
|
5月前
|
存储 算法 大数据
Python算法高手的必修课:深入理解分治法、贪心算法、动态规划,让你的代码更智能!
【7月更文挑战第9天】在Python算法学习中,分治法(如归并排序)将大问题分解为小部分递归解决;贪心算法(如货币找零)在每步选择局部最优解尝试达到全局最优;动态规划(如斐波那契数列)通过存储子问题解避免重复计算,解决重叠子问题。掌握这三种方法能提升代码效率,解决复杂问题。
55 1
|
5月前
|
算法 索引 Python
逆袭算法界!Python分治法、贪心算法、动态规划深度剖析,带你走出算法迷宫!
【7月更文挑战第8天】分治法,如快速排序,将大问题分解并合并解;贪心算法,选择局部最优解,如活动选择;动态规划,利用最优子结构避免重复计算,如斐波那契数列。Python示例展示这些算法如何解决实际问题,助你精通算法,勇闯迷宫。
50 1