蓝桥杯刷题——路径(最短路)

476 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。 这是蓝桥杯常考的题型,21年的省赛题目

题目

image.png

思路

可以看到,这道题目核心思想就是最短路,是无向边的图,求单源最短路径,就算是有向边的,也是一样的做法。首先要完成一个初始化,也就是构图,对所有的点和他们之间的距离放进一个二维数组,距离要用到一个最小公倍数,这里写一个最小公倍数的函数即可,可用最小公约数来完成。初始化完成之后。初始点1和剩下的2020个点之间的距离就用一个一维数组dis[2030]存放即可。之后正式进入最短路的核心算法。每次先取dis[2030]数组中最小的值并且要求这个点从未被选取过,然后标记这个点已被选取过。然后利用这个点为中间点,用这个点来更新dis[2030]中的所有点,如果小于原先值,就可更新。完成整个循环后,直接输出dis[2021],最小的单源路径的答案就是这个了。

代码

#include<bits/stdc++.h>
using namespace std;
const int m=100000000;
int D[2030][2030];
int dis[2030];
int vis[2030];
int gcd(int a,int b){
	while(b){
		int c=b;
		b=a%b;
		a=c;
	}
	return a;
}
void init(){//初始化函数
	for(int i=1;i<=2021;i++){
		for(int j=1;j<=2021;j++){
			if(abs(i-j)<=21&&abs(i-j)>0){
				D[i][j]=i*j/gcd(i,j);//利用最小公约数求最小公倍数 
			}else
				D[i][j]=m;
		}
		if(i<=21&&i>1){//1和任何数的公倍数就是它的本省
			dis[i]=i;
		}else
			dis[i]=m;
	}
}
int main(){
	init();
	for(int i=1;i<2021;i++){//单源最短路径的核心算法
		int mmin=m;
		int k=0;
		for(int j=1;j<=2021;j++){
			if(mmin>dis[j]&&!vis[j]){
				mmin=dis[j];
				k=j;
			}
		}
		vis[k]=1;
		for(int s=1;s<=2021;s++){
			if(D[k][s]<m){
				if(dis[s]>dis[k]+D[k][s]){
					dis[s]=dis[k]+D[k][s];
				}
			}
		}
	}
	cout<<dis[2021];
	return 0;
}