「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战」。
这是蓝桥杯19年省赛的一道填空题,答案其实自己看一下题目就能得出来了,甚至不需要去设计什么算法,但如果题目真的要出复杂一点,用肉眼去看是得不到答案了,这道题就是一个经典的迪杰斯特拉算法题目,数据结构中应有学过。
题目
思路
看到求单源最短路径的题目,我们应当是能够想到用迪杰斯特拉算法来解决的。能想到这个算法,然后脑海里能够清晰的复现出这个算法流程,这道题目应该就能够做出来了。无向图,我们肯定是要先构建出无向图的,用一个二维数组来存储就可以了,哪个节点到哪个节点就可以作为索引了,而它们之间的值就是他们的在无向图中的长度了。构建好无向图,就开始设计迪杰斯特拉算法了。
迪杰斯特拉算法
大致说明一下迪杰斯特拉算法,这个算法有点像是贪心算法,都是找到当前最好的一个情况,再接着往下做。我们将给定的节点分为两组,一组是已经找到从源点开始到这个点的最短路径,为s组,另一组是还没有找到的,为f组。当f组中的所有节点都放到s组中时,算法也就结束了。而一开始,很显然,s组中只有源点这一个点在,这里的最短路径就设为0。第二个点就按索引的顺序来好了,第二个点是可以随机选取的。每次最短路径还要再进行一个判断就是:
for(int j=1;j<=n;j++) { dist[j]=min(dist[j],dist[t]+g[t][j]); }
这里n就是n个节点,dist是源点到这个节点的最短路径,g存储的是无向图中的值哦。每次选取节点都要选取最短路径的。代码如下:
int t=-1;//要选取的节点
for(int j=1;j<=n;j++) {
if(!vis[j]&&(t==-1||dist[j]<dist[t]))//要最短并且没有被选过的
t=j;
}
vis[t]=1;//选了之后要设置为1代表已经选过。
总代码
#include <bits/stdc++.h>
using namespace std;
const int N=21,n=19;//共19个字母
int dist[N];
int g[N][N];
void add(int x,int y,int c)
{
g[x][y]=g[x][y]=c;
}
int vis[N];
int diskt()
{
memset(dist,27,sizeof dist);
dist[1]=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&(t==-1||dist[j]<dist[t]))
t=j;
}
vis[t]=1;
for(int j=1;j<=n;j++)
{
dist[j]=min(dist[j],dist[t]+g[t][j]);
}
}
return dist[n];
}
int main()
{
memset(g,27,sizeof(g));
for(int i=1;i<=19;i++){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
cout<<diskt();
return 0;
}