Question:
Result:
10266837
Solve:
一看到题,最短路板子题实锤,而且是无负权,那就Ploryd或者Dijkstra算法就ok
首先存数据,那就直接用邻接矩阵就行,不同的点之间的权值记为无穷大
观察数据范围,Ploryd算法会超时,但这是填空题,最暴力的Ploryd也无妨,多跑一会而已,用Dijkstra算法的话n^2即可,之后有空的话就补上Dijkstra的(n+m)logm(优先队列)解法。
Code:
Floryd算法:
#include <bits/stdc++.h>
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 <<edge[1][2021];
return 0;
}
Dijkstra算法(n^2):
#include <bits/stdc++.h>
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 <bits/stdc++.h>
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_queue<Node>q;
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 <<dis[2021];
return 0;
}
最后附上蓝桥杯汇总链接:蓝桥杯C/C++A组省赛历年真题题解
声明:图片均来源于蓝桥杯官网,以个人刷题整理为目的,如若侵权,请联系删除~