Dijkstra算法
一.最短路径的最优子结构性质
该性质描述为:如果P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径。即如果存在一条从i到j的最短路径(Vi.....Vk,Vj),那么(Vi...Vk)也必定是从i到k的最短路径。
二.定义
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
三.算法思想
每次新扩展一个距离最短的点,更新与其相邻的点的距离。当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性。不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破坏了已经更新的点距离不会改变的性质。
四.算法实现
初始时,源点s的路径长度值被赋为0(d[s]=0), 同时把所有其他顶点的路径长度设为无穷大,如果存在一条从u到v的边,那么从s到u的最短路径可以通过将边(u,v)添加到尾部来拓展一条从s到v的路径。这条路径的长度是d[u]+w(u,v)。如果这个值比目前已知的d[v]的值要小,我们可以用新值来替代当前d[v]中的值。
算法结束时,d[v]中储存的便是从s到v的最短路径,或者如果路径不存在的话是无穷大。
时间复杂度 O(n²)
一道水题
最短路
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 83466 Accepted Submission(s): 36120
输入保证至少存在1条商店到赛场的路线。
裸题,直接上代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxx=999999999;
const int INF=110;
int n,m;
int mapp[INF][INF];
int dis[INF];
bool visited[INF];
void Dijkstra(int v0)
{
for(int i=1; i<=n; i++){
dis[i]=mapp[1][i];
visited[i]=0;
}
visited[v0]=1;
for(int i=1; i<=n; i++){
int p,minn=maxx;
for(int j=1; j<=n; j++){
if(!visited[j] && dis[j]<minn){
p=j;
minn=dis[j];
}
}
visited[p]=1;
for(int j=1; j<=n; j++){
if(!visited[j] && dis[p]+mapp[p][j]<dis[j]){
dis[j]=dis[p]+mapp[p][j];
}
}
}
return ;
}
int main()
{
while(cin>>n>>m){
if(n==0 && m==0) break;
int a,b,c;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
mapp[i][j]=maxx;
}
}
for(int i=1; i<=m; i++){
cin>>a>>b>>c;
mapp[a][b]=mapp[b][a]=c;
}
Dijkstra(1);
cout<<dis[n]<<endl;
}
return 0;
}
再来一道不怎么裸的题
6487: Cosmic Rays
时间限制: 1 Sec 内存限制: 128 MB提交: 85 解决: 43
[提交][状态][讨论版][命题人:admin]
题目描述
There are N circular barriers deployed on the plane. The center and the radius of the i-th barrier are (xi,yi) and ri, respectively. The barriers may overlap or contain each other.
A point on the plane is exposed to cosmic rays if the point is not within any of the barriers.
Snuke wants to avoid exposure to cosmic rays as much as possible during the travel. Find the minimum possible duration of time he is exposed to cosmic rays during the travel.
Constraints
All input values are integers.
−109≤xs,ys,xt,yt≤109
(xs,ys) ≠ (xt,yt)
1≤N≤1,000
−109≤xi,yi≤109
1≤ri≤109
输入
xs ys xt yt
N
x1 y1 r1
x2 y2 r2
:
xN yN rN
输出
样例输入
-2 -2 2 2
1
0 0 1
样例输出
3.656854249
提示
An optimal route is as follows:
![](http://exam.upc.edu.cn/upload/image/20180414/20180414195028_43891.jpg)
求出从起点到终点走过的最短的不在圆上的距离
因为要尽量在圆内走,所以将每个圆心都看做一个可以走的点,计算出点与点之间的距离,存在二维数组里,这样就变成了最短路的题
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e3+10;
const int INF = 2e9;
bool vis[MAXN];
double val[MAXN][MAXN];
double ans[MAXN];
struct node {
int x, y, r;
} e[MAXN];
void Dijkstra( int n, int beg) {
for (int i = 0; i < n; i++) {
ans[i] = INF;
vis[i] = false;
}
ans[beg] = 0;
for (int j = 0; j < n; j++) {
int k = -1;
double min = INF;
for (int i = 0; i < n; i++) {
if (!vis[i] && ans[i] < min) {
min = ans[i];
k = i;
}
}
if (k == -1) {
break;
}
vis[k] = true;
for (int i = 0; i < n; i++) {
if (!vis[i] && ans[k] + val[k][i] < ans[i]) {
ans[i] = ans[k] + val[k][i];
}
}
}
}
int main() {
int n;
int sx, sy, ex, ey;
cin >> sx >> sy >> e[0].x >> e[0].y >> n;
e[0].r = 0;
e[n + 1].r = 0;
e[n + 1].x=sx;
e[n+1].y=sy;
n++;
for (int i = 1; i < n; i++) {
cin >> e[i].x >> e[i].y >> e[i].r;
}
for (int i = 0; i <= n; i++) {
for (int j = i+1; j <= n; j++) {
val[i][j] = (double)(sqrt((e[i].x - e[j].x)*(e[i].x - e[j].x) +(e[i].y - e[j].y)*(e[i].y - e[j].y)) - e[i].r - e[j].r);
if(val[i][j]<0) val[i][j]=0;
val[j][i] = val[i][j];
}
}
Dijkstra(n + 1, n);
printf("%.9f\n",ans[0]);
return 0;
}