一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。 这是蓝桥杯常考的题型,21年的省赛题目
题目
思路
可以看到,这道题目核心思想就是最短路,是无向边的图,求单源最短路径,就算是有向边的,也是一样的做法。首先要完成一个初始化,也就是构图,对所有的点和他们之间的距离放进一个二维数组,距离要用到一个最小公倍数,这里写一个最小公倍数的函数即可,可用最小公约数来完成。初始化完成之后。初始点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;
}