一、要点
贪心算法的基本要素
1、贪心选择性质
整体最优解是一系列局部最优解的选择,同时也是贪心与动态规划最主要的区别。
贪心自上而下解决问题,动态规划自下而上解决问题。
动态规划要求解所有子问题,而贪心只需要局部最优解。
2、最优子结构性
当一个问题的最优解包含其子问题的最优解时,我们称问题具有最优子结构性。
3、只有一个FOR循环
二、问题
1、活动安排问题
//s[]存开始时间,e[]存结束时间,A[]存安排的活动
//e[]按照由小到大排列,先结束的排在前面
void GreedySelector(int n ,type s[] ,type e[] ,bool A[] )
{
A[I]=true;//活动1默认安排
int j =1;
for(int i =1;i<=n;i++)
{
if(s[i]>=e[j])//如果下一个活动的开始时间晚于当前活动的结束时间,将下一个活动置为true;
{
A[i]=true;
j=i;
}
else
A[i]=false;
}
}
2、0-1背包
public class test{
public void tanxin()
{
float rest= bag;
int j=0;
float b=0;
for(int i=2;i>=0;i--)
{
if(goods[i].weight<=rest)
{
goods[i].bn=goods[i].weight;
goods[i].an=goods[i].value;
rest=rest-goods[i].weight;
b=b+goods[i].value;
j++;
}
else if(rest>0){
float a =(float)rest/goods[i].weight;
goods[i].an=goods[i].value*a;
goods[i].bn=goods[i].weight*a;
b=b+(goods[i].value*a);
rest=0;
}
}
3、哈夫曼编码
首先获得各个字符出现的频率
找出最小的两个相加,如果两个数的和正好是下一步的两个最小数的其中的一个那么这个树直接往上生长就可以了。如果这两个数的和比较大不是下一步的两个最小数的其中一个那么,就并列生长,如下图所示
算法复杂度为 O(nlogn)
4、单源最短路径
其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其他顶点之间的最短路径长度。
算法复杂度为:n平方
最小生成树
prim算法
以点出发
Kruskal算法
从边出发
算法复杂度:O( n平方)