《趣学算法》之贪心算法(下)

本文深入探讨贪心算法在解决实际问题中的应用,包括求解最短路径问题,利用哈夫曼编码进行高效传输,以及构建最小生成树实现校园网络优化。通过详细算法设计和实例解析,揭示贪心策略在各个问题中的智慧选择。

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

本篇文章接上(上)的经典例应用:
④一场说走就走的旅行——最短路径

当你想要旅行的地点有多个,想要计算最短路线,估算所需时间时,该如何计算?

思考过程】这是一个求单源最短路径的问题。给定有向带权图G=(V,E),其中每条边的权是非负实数。此外,给定V中的一个顶点,成为源点。现在要计算从源到所有其他各顶点的最短路径长度,这里路径长度指路上各边的权之和。如何求源头点到其他各点的最短路径呢?

算法设计】(1)数据结构。设置地图的带权邻接矩阵为map[] [] ,即如果从源点 u 到顶点 i 有边,就令 map[u] [i] 等于 <u,i> 的权值,否则 map[u] [i]=∞(无穷大);采用一维数组 dist[i] 来记录从源点到 i 顶点的最短路径长度;采用一维数组 p[i] 来记录最短路径上 i 顶点的前驱。
(2)初始化。令集合 S={u},对于集合V-S中的所有顶点 x ,初始化 dist[i]=map[u][i],如果源点 u 到顶点 i 有边相连,初始化 p[i]=u,否则 p[i]=-1。
(3)找最小。在集合 V-S 中依照贪心策略来寻找使得 dist[j]具有最小值的顶点 t ,即 dist[t]=min(dist[j] | j 属于V-S集合),则顶点 t 就是属于集合V-S中距离源点 u 最近的顶点。
(4)加入S战队。 将顶点 t 加入集合S中,同时更新V-S。
(5)判结束。 如果集合V-S为空,算法结束,否则转(6)。
(6)借东风。在(3)中已经找到了源点到 t 的最短路径,那么对集合V-S中所有与顶点 t 相邻的顶点 j ,都可以借助 t 走捷径。如果 dist[j] > dist[t] + map[t] [j],则 dist[j] = dist[t] + map[t] [j],记录顶点 j 的前驱为 t,有 p[j] = t,转(3)。
由此,可求得从源点 u 到图G的其余各个顶点的最短路径及长度,也可通过数组 p[]逆向找到最短路径上经过的城市。

代码实现

#include <cstdio>
#include<iostream>
#include<cstring>
#include<windows.h>
#include<stack>
using namespace std;
const int N = 100;  //城市的个数可修改
const int INF = le7;  //初始化无穷大为10000000
int map[N] [N],dist[N],p[N],n,m;  //n为城市的个数,m为城市间路线的条数
bool flag[N];   //如果flag[i]等于ture,说明顶点i已经加入到集合S;否则顶点i属于集合V-S
void Dijkstra(int u){
   
	for(int i=1;i<n;i++){
    
		dist[i]=map[u][i];  //初始化源点u到其他各个顶点的最短路径长度
		flag[i] = flase;
		if(dist[i] == INF)
			p[i]=-1;  //源点u到该顶点的路径长度为无穷大,说明顶点i与源点u不相邻
		else
			p[i]=u;  //说明顶点i与源点u相邻,设置顶点i的前驱p[i]=u
	}
	dist[u]=0;
	flag[u]=ture;  //初始时,集合S中只有一个元素:源点u
	for(int i=1;i<n;i++){
     
		int temp = INF,t=u;
		for(int j=1;j<=n;j++){
     //在集合V-S中寻找距离源点u最近的顶点t
			if(!flag[j]&&dist[j]<temp){
   
				t = j;
				temp = dist[j];
			}
			if(t==u)   return;  //找不到t,跳出循环
			flag[t]=ture;  //否则,将t加入集合
			for(int j=1;j<=n;j++){
     //更新集合V-S中与t邻接的顶点与源点u的距离
				if(!flag[j]&&map[t][j]<INF){
     //!flag[j]表示j在V-S中
					if(dist[j]>(dist[t]+map[t][j])){
   
						dist[j]=dist[t]+map[t][j];
						p[j]=t;
					
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值