目录
一、贪心法的基本思想
二、贪心法的基本要素
1.最优子结构性质
2.贪心选择性质
三、贪心法的解题步骤及算法设计模式
步骤:
1.分解:
2.解决:
3.合并:
设计模式:
四、会场安排问题
五、最优装载问题
六、单元最短路径问题
一、贪心法的基本思想
贪心法是一种稳扎稳打的算法,他从问题的摸一个初始解出发,在每一个阶段都根据贪心策略来做出当前最优决策,逐步逼近给定目标,尽可能快地求得更好的解。当达到算法中的某一步不能再继续前进时,算法终止。也可以理解为:以逐步的局部最优,达到最终的全局最优。
二、贪心法的基本要素
1.最优子结构性质
当一个问题的最优解一定包含其他子问题的最优解时,称此问题具有最优子结构性质。(一个问题能够分解成各个子问题来解决,通过各个子问题的最优解能递推到原问题的最优解,此时原问题的最优解一定包含各个子问题的最优解,这是能够采用贪心法来求解问题的关键)
在分析问题是否具有最优子结构性质时,通常先设出问题的最优解,给出子问题的解一定是最优的结论。然后,采用反证法证明“子问题的解一定时最优的”结论成立。证明思路是:设原问题的最优解导出子问题的解不是最优的,然后在这个假设下可以构造出比原问题的最优解更好的解,从而导致矛盾。
2.贪心选择性质
贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择获得,即通过一系列的逐步局部最优选择使得最终的选择方案是全局最优的。其中每次所做的选择,可以依赖于以前的选择,但不依赖于将来所做的选择。
贪心选择性质所做的是一个非线性的子问题处理流程,即一个子问题并不依赖于另一个子问题,但是子问题间有严格的顺序性。
三、贪心法的解题步骤及算法设计模式
步骤:
1.分解:
将原问题分解为若干个相互独立的阶段。
2.解决:
对于每个阶段依据贪心策略进行贪心选择,求出局部的最优解。
3.合并:
将各个阶段的解合并为原问题的一个可行解。
设计模式:
四、会场安排问题
此问题的核心思想是:每次从剩下未安排的会议中选择具有最早结束时间且不会与已安排的会议重叠的会议来安排。这样可以使下一个会议尽快开始。
1)实现活动安排问题的贪心算法。
测试数据可选用:
i
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
Begin
|
1
|
3
|
2
|
5
|
3
|
5
|
6
|
8
|
8
|
2
|
End
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
运算截图如下:
编辑
五、最优装载问题
2)实现最优装载的贪心算法。
测试数据可选用:
假设轮船限重12kg
i
|
1
|
2
|
3
|
4
|
5
|
Wi(kg)
|
8
|
4
|
2
|
5
|
7
|
代码运行截图如下:
编辑
六、单元最短路径问题
3)单源最短路径的贪心算法。
测试数据可选用下图,1为源点:
编辑
#include<iostream>
#include<string>
using namespace std;
const int inf = INT_MAX;
void Dijkstra(int n, int source, int *dist, int *prev, int c[8][8])
{
//表示点是否在s集合里
bool *s=new bool[n];
for (int i = 0; i < n; i++)
{
dist[i] = c[source][i];
//初始化时,除了source外所有结点都不在s集合
s[i] = i == source ? true : false;
//结点可达,前驱结点记作源点
//结点不可达,前驱结点记作-1
prev[i] = dist[i] == inf ? -1 : source;
}
for ( i = 1; i < n; i++)//找n-1个点
{
int mindist = inf;
int newnode;//记录距离source最近的点
for (int j = 0; j < n; j++)
{
//j点不在s集合中,且到soutce的距离小于上一个点到source的距离
if (!s[j] && dist[j] < mindist)
{
newnode = j;
mindist = dist[newnode];
}
}
s[newnode] = true;
for ( j = 0;j < n; j++)//当s集合加入新结点时,需要更新dist和prev
{
if (!s[j] && c[newnode][j] < inf)
{
//点不在s中,且与新节点相邻
int newdist = dist[newnode]+c[newnode][j];//新结点到source的距离+新结点到j点的距离
if (newdist < dist[j])
{
dist[j] = newdist;
prev[j] = newnode;//新结点成了前驱结点
}
}
}
}
}
int main()
{
int c[8][8] = {
{0,2,inf,1,inf,3,inf,inf},
{inf,0,6,inf,5,inf,inf,inf},
{inf,inf,0,inf,inf,inf,inf,6},
{inf,10,inf,0,inf,inf,2,inf},
{inf,inf,9,inf,0,inf,inf,4},
{inf,inf,inf,5,inf,0,4,inf},
{inf,7,inf,inf,3,inf,0,8},
{inf,inf,inf,inf,inf,inf,inf,0}
};
int n = 8;
int dist[8];
int prev[8];
int source = 0;
Dijkstra(8, source, dist, prev, c);
cout << "源点到各点的最短路径为:";
for (int i = 0; i < n; i++)
{
cout << dist[i] << " ";
}
return 0;
}
运行结果如图所示:
编辑
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
评论(0)