利用图求最短路径的算法(Dijkstra和Floyd),Floyd时间复杂度较高,但这题可以勉强用,大概需要25 s时间,不懂这两个算法的可以去看一下算法笔记,这两个算法还是很好用的。
Dijkstra:
#include<iostream>
#include<cstring> //memset()原型
using namespace std;
const int N=3000;
const int INF=0x3f; //这里可以理解为无穷大
int graph[N][N]; //邻接矩阵存储图
int dist[N]; //记录最短路径值
bool visited[N]; //判断节点是否访问
int gcd(int a,int b){ //最大公约数
return b==0?a:gcd(b,a%b);
}
int lem(int a,int b){ //最小公倍数
return a*b/gcd(a,b);
}
int dijkstra(int n){
//初始化
memset(dist,INF,sizeof(dist));
memset(visited,false,sizeof(visited));
dist[1]=0;
for(int i=1;i<=n;++i){
int k=-1;
for(int j=1;j<=n;++j){ //获取距离源点最近点
if(!visited[j]&&(k==-1||dist[j]<dist[k])){
k=j;
}
}
visited[k]=true;
for(int j=1;j<=n;++j){
if(dist[k]+graph[k][j]<dist[j]){
dist[j]=dist[k]+graph[k][j];
}
}
}
if(dist[n]==INF) return -1;
return dist[n];
}
int main(){
int n=2021; //节点数
//初始化
memset(graph,INF,sizeof(graph));
//构图
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(abs(i-j)<=21){
graph[i][j]=lem(i,j);
}
}
}
//求出最短路径,输出结果
cout<<dijkstra(n)<<endl;
return 0;
}
Floyd:
#include<iostream>
#include<cstring>
using namespace std;
const int N=3000;
const int INF=0x3f;
int graph[N][N];
int gcd(int a,int b){ //最大公约数
return b==0?a:gcd(b,a%b);
}
int lem(int a,int b){ //最小公倍数
return a*b/gcd(a,b);
}
void Floyd(int n){
for(int k=1;k<=n;++k){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(graph[i][k]+graph[k][j]<graph[i][j])
graph[i][j]=graph[i][k]+graph[k][j];
}
}
}
}
int main(){
int n=2021; //节点数
//初始化
memset(graph,INF,sizeof(graph));
//构图
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(abs(i-j)<=21){
graph[i][j]=lem(i,j);
}
}
}
//求出最短路径,输出结果
Floyd(n);
cout<<graph[1][2021];
return 0;
}