蓝桥杯.路径(最短路)

Question:

蓝桥杯.路径(最短路)_第1张图片

Result: 

10266837

Solve:

一看到题,最短路板子题实锤,而且是无负权,那就Ploryd或者Dijkstra算法就ok

首先存数据,那就直接用邻接矩阵就行,不同的点之间的权值记为无穷大

观察数据范围,Ploryd算法会超时,但这是填空题,最暴力的Ploryd也无妨,多跑一会而已,用Dijkstra算法的话n^2即可,之后有空的话就补上Dijkstra的(n+m)logm(优先队列)解法。

Code:

Floryd算法:

#include 
using namespace std;
typedef long long ll;
#define MAXN 1e18
ll edge[2025][2025];
int n = 2021;
void Ploryd()
{
	//三重循环更新 
	for(int k = 1; k <= n; k++)
	for(int i = 1; i <= n; i++)
	for(int j = 1; j <= n; j++)
		edge[i][j] = min(edge[i][j], edge[i][k] + edge[k][j]);
}
int main(void)
{
	//边权值读入
	 for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == j) edge[i][j] = 0;
            else if(abs(i - j) <= 21) edge[i][j] = edge[j][i] = i * j / __gcd(i, j);
            else edge[i][j] = edge[j][i] = MAXN;
        }
    }
	Ploryd();
	cout <

Dijkstra算法(n^2):

#include 
using namespace std;
typedef long long ll;
#define MAXN 1e18
//边数组 
ll edge[2025][2025], n = 2021;
//最短路数组,前驱数组 
ll dist[2025], pre[2025];
//标记数组 
bool vis[2025];
void Dijkstra()
{
	//初始化 
	for(int i = 1; i <= n; i++){
		vis[i] = false;
		dist[i] = edge[1][i];
		if(edge[1][i] < MAXN){
			pre[i] = 1;
		}
	}
	//标记 
	vis[1] = true; dist[1] = 0;
	//n-1趟循环 
	for(int i = 1; i < n; i++){
		//找出所有未访问的点中距离起点最近的点 
		int temp;
		ll minn = MAXN;
		for(int j = 1; j <= n; j++){
			if(!vis[j] && dist[j] < minn){
				minn = dist[j];
				temp = j;
			}
		}
		vis[temp] = true;
		//以temp为中间点,刷新起点到各点的最短路径 
		for(int j = 1; j <= n; j++){
			if((dist[temp]+edge[temp][j] < dist[j]) && !vis[j]){
				dist[j] = dist[temp]+edge[temp][j];
				pre[j] = temp;
			}
		}
	}
}
int main(void)
{
	//边权值读入
	 for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == j) edge[i][j] = 0;
            else if(abs(i - j) <= 21) edge[i][j] = edge[j][i] = i * j / __gcd(i, j);
            else edge[i][j] = edge[j][i] = MAXN;
        }
    }
	Dijkstra();
	printf("%lld", dist[2021]);
	return 0;
}

Dijkstra(优先队列):

来补了~

#include 
using namespace std;
typedef long long ll;
//邻接矩阵 
ll a[2025][2025];
// 最短路存放以及标记 
ll dis[2025]; 
bool vis[2025];
//结构体声明,序号,距离 
struct Node{
	int x, dis;
	//按照dis大小比较 
	bool operator < (const Node &a) const{
		return dis > a.dis;
	}
};
//优先队列 
priority_queueq;

void Dijkstra()
{
	//初始化 
	for(int i = 1; i <= 2021; i++){
		dis[i] = 1e9;
		vis[i] = false;
	}
	Node temp;
	dis[1] = 0;
	temp.x = 1; temp.dis = 0;
	//入队 
	q.push(temp);
	
	while(!q.empty())
	{
		Node node = q.top(); q.pop();
		//处理重复入队 
		if(vis[node.x]) continue;
		
		vis[node.x] = true;
		//去更新与node.x有边相连的点的最短路 
		for(int i = 1; i <= 2021; i++){
			if(vis[i]) continue;
			if(dis[node.x] + a[node.x][i] < dis[i]){	
				dis[i] = dis[node.x] + a[node.x][i];
				//可更新的话就入队 
				Node next;
				next.x = i; next.dis = dis[i];
				q.push(next);
			}
		}
	}
}
int main(void)
{
	//构建图 
	for(int i = 1; i <= 2021; i++)
	for(int j = 1; j <= 2021; j++){
		if(i == j) a[i][j] = 0;
		else if(abs(i - j) <= 21)
			a[i][j] = a[j][i] = i*j/__gcd(i, j);
	    else
	    	a[i][j] = a[j][i] = 1e9;
	} 
	Dijkstra();
	cout <

最后附上蓝桥杯汇总链接:蓝桥杯C/C++A组省赛历年真题题解

声明:图片均来源于蓝桥杯官网,以个人刷题整理为目的,如若侵权,请联系删除~

你可能感兴趣的:(蓝桥杯,蓝桥杯,算法,c++,图论)