The shortest path on earth and on the map. Determining the distance between two parallel lines The shortest distance between 2 points

Having marked two points on the blackboard with chalk, the teacher offers the young schoolboy a task: to draw the shortest path between both points.

The student, after thinking, carefully draws a winding line between them.

- That's the shortest way! – the teacher is surprised. -Who taught you that?

- My dad. He is a taxi driver.

The drawing of a naive schoolboy is, of course, anecdotal, but wouldn’t you smile if you were told that the dotted arc in Fig. 1 - the shortest route from the Cape of Good Hope to the southern tip of Australia!

Even more striking is the following statement: shown in Fig. 2 the roundabout route from Japan to the Panama Canal is shorter than the straight line drawn between them on the same map!

Rice. 1. On a sea map, the shortest route from the Cape of Good Hope to the southern tip of Australia is indicated not by a straight line (“loxodrome”), but by a curve (“orthodrome”)


All this looks like a joke, but meanwhile, before you are indisputable truths, well known to cartographers.




Rice. 2. It seems incredible that the curved path connecting Yokohama to the Panama Canal on a sea map is shorter than a straight line drawn between the same points


To clarify the issue, we will have to say a few words about maps in general and sea maps in particular. Depicting parts of the earth's surface on paper is not an easy task, even in principle, because the earth is a ball, and it is known that no part of a spherical surface can be unfolded on a plane without folds and tears. One inevitably has to put up with inevitable distortions on maps. Many ways of drawing maps have been invented, but all maps are not free from shortcomings: some have distortions of one kind, others of another kind, but there are no maps without distortions at all.

Sailors use maps drawn according to the method of an ancient Dutch cartographer and mathematician of the 16th century. Mercator. This method is called “Mercatorian projection”. It is easy to recognize a sea map by its rectangular grid: the meridians are depicted on it as a series of parallel straight lines; circles of latitude are also straight lines, perpendicular to the first ones (see Fig. 5).

Imagine now that you need to find the shortest path from one ocean port to another, lying on the same parallel. On the ocean, all paths are accessible, and traveling there along the shortest path is always possible if you know how it runs. In our case, it is natural to think that the shortest path goes along the parallel on which both ports lie: after all, on the map it is a straight line, and what could be shorter than a straight path! But we are mistaken: the parallel path is not the shortest at all.

Indeed: on the surface of a ball, the shortest distance between two points is the great circle arc connecting them. But the circle of parallels - small circle. The arc of a large circle is less curved than the arc of any small circle drawn through the same two points: a larger radius corresponds to a smaller curvature. Stretch a thread on the globe between our two points (cf. Fig. 3); you will be convinced that it will not lie along the parallel at all. A stretched thread is an indisputable indicator of the shortest path, and if it does not coincide with a parallel on the globe, then on a sea map the shortest path is not indicated by a straight line: remember that circles of parallels are depicted on such a map as straight lines, but any line that does not coincide with a straight line , There is curve .



Rice. 3. A simple way to find the truly shortest path between two points: you need to pull a thread on a globe between these points


After what has been said, it becomes clear why the shortest path on a sea map is depicted not as a straight line, but as a curved line.

They say that when choosing a direction for Nikolaevskaya (now Oktyabrskaya) railway There were endless debates about which route to take it. The controversy was put to an end by the intervention of Tsar Nicholas I, who solved the problem literally “straightforward”: he connected St. Petersburg with Moscow along a line. If this had been done on a Mercator map, the result would have been an embarrassing surprise: instead of a straight road, the road would have turned out crooked.

Anyone who does not avoid calculations can make sure with a simple calculation that the path that seems crooked to us on the map is actually shorter than the one that we are ready to consider straight. Let our two harbors lie on the 60th parallel and are separated by a distance of 60°. (Whether such two harbors actually exist is, of course, immaterial to the calculation.)



Rice. 4. To calculate the distances between points A and B on a ball along a parallel arc and along a great circle arc


In Fig. 4 point ABOUT - center of the globe, AB – arc of the circle of latitude on which the harbors lie A and B; V it's 60°. The center of the circle of latitude is at the point WITH Let's imagine that from the center ABOUT the globe is drawn through the same harbors by an arc of a great circle: its radius OB = OA = R; it will pass close to the drawn arc AB, but will not coincide with it.

Let's calculate the length of each arc. Since the points A And IN lie at latitude 60°, then the radii OA And OB amount to OS(the axis of the globe) an angle of 30°. In a right triangle ASO leg AC (=r), lying opposite an angle of 30°, equal to half the hypotenuse JSC;

Means, r=R/2 Arc length AB is one-sixth the length of the circle of latitude, and since this circle has half the length of the large circle (corresponding to half the radius), then the arc length of the small circle



To now determine the length of the arc of a great circle drawn between the same points (i.e., the shortest path between them), we need to find out the magnitude of the angle AOB. Chord AS, subtending an arc of 60° (of a small circle), is the side of a regular hexagon inscribed in the same small circle; That's why AB = r=R/2

Having drawn a straight line O.D. connecting the center ABOUT globe with middle D chords AB, we get a right triangle ODA, where is the angle D – direct:

DA= 1/2 AB and OA = R.

sinAOD=AD: AO=R/4:R=0.25

From here we find (from the tables):

=14°28",5

and therefore

= 28°57".

Now it is not difficult to find the required length of the shortest path in kilometers. The calculation can be simplified if we remember that the length of a minute of a great circle of the globe is

We learn that the path along the circle of latitude, depicted on the sea map as a straight line, is 3333 km, and the path along the great circle - along the curve on the map - is 3213 km, i.e. 120 km shorter.

Armed with a thread and having a globe at hand, you can easily check the correctness of our drawings and make sure that the arcs of great circles really lie as shown in the drawings. Shown in Fig. 1 supposedly “straight” sea ​​route from Africa to Australia is 6020 miles, and the “curve” is 5450 miles, i.e. shorter by 570 miles, or 1050 km. The “direct” air route from London to Shanghai on the sea map cuts the Caspian Sea, while in fact the shortest route lies north of St. Petersburg. It is clear what role these issues play in saving time and fuel.

If in the era of sailing shipping time was not always valued - then “time” was not yet considered “money” - then with the advent of steam ships one has to pay for every ton of coal that is excessively consumed. That is why nowadays ships are guided along the truly shortest route, often using maps made not in the Mercator projection, but in the so-called “central” projection: on these maps, the arcs of great circles are depicted as straight lines.

Why did earlier navigators use such deceptive maps and choose unfavorable routes? It is a mistake to think that in the old days they did not know about the now indicated feature of sea charts. The matter is explained, of course, not by this, but by the fact that maps drawn according to Mercator’s method have, along with inconveniences, benefits that are very valuable for sailors. Such a map, firstly, depicts individual small parts of the earth's surface without distortion, maintaining the angles of the contour. This is not contradicted by the fact that with distance from the equator, all contours noticeably stretch. In high latitudes, the stretching is so significant that a nautical map gives a person unfamiliar with its features a completely false idea of ​​the true size of the continents: Greenland seems the same size as Africa, Alaska is larger than Australia, although Greenland is 15 times smaller than Africa, and Alaska together with Greenland half the size of Australia. But a sailor who is well acquainted with these features of the map cannot be misled by them. He puts up with them, especially since within small areas the sea chart gives an exact resemblance to nature (Fig. 5).

But a nautical chart greatly facilitates solving navigational practice problems. This is the only type of map on which the path of a ship moving on a constant course is depicted as a straight line. To walk on a “constant course” means to consistently adhere to one direction, one specific “point of reference,” in other words, to walk in such a way as to intersect all meridians at an equal angle. But this path (“loxodrome”) can be depicted as a straight line only on a map on which all meridians are straight lines parallel to each other. And since on the globe the circles of latitude intersect with the meridians at right angles, then on such a map the circles of latitude should be straight lines perpendicular to the lines of the meridians. In short, we arrive at exactly the coordinate grid that makes up characteristic feature sea ​​map.




Rice. 5. Nautical or Mercator map of the globe. Such maps greatly exaggerate the size of contours distant from the equator. What, for example, is bigger: Greenland or Australia? (Answer in text)


The predilection of sailors for Mercator's maps is now understandable. Wanting to determine the course to follow when going to the designated port, the navigator applies a ruler to the end points of the path and measures the angle it makes with the meridians. Keeping in the open sea all the time in this direction, the navigator will accurately bring the ship to the target. You see that the “loxodrome” is, although not the shortest and not the most economical, but in a certain respect a very convenient route for a sailor. To reach, for example, from the Cape of Good Hope to the southern tip of Australia (see Fig. 1), one must always keep one course S 87°.50". Meanwhile, to bring the ship to the same final point by the shortest route (according to the "orthodrome" "), it is necessary, as can be seen from the figure, to continuously change the course of the ship: start with the course S 42°.50", and end with the course N 53°.50" (in this case, the shortest path is not even feasible - it rests on the ice wall of the Antarctic ).

Both paths - along the “loxodrome” and along the “orthodrome” - coincide only when the path along a great circle is depicted on a sea map as a straight line: when moving along the equator or along the meridian. In all other cases, these paths are different.

DISTANCE, distances, avg. 1. A space separating two points, a gap between something. The shortest distance between two points in a straight line. He lives two kilometers from us. “The commandant let them get as close as possible... Ushakov's Explanatory Dictionary

distance- noun, p., used often Morphology: (no) what? distances, why? distance, (see) what? distance, what? distance, about what? about distance; pl. What? distance, (no) what? distances, what? distances, (I see) what? distances, what? distances... Dmitriev's Explanatory Dictionary

distance- I; Wed The space separating two points, two objects, etc., the gap between whom, than l. Shortest river between two points. R. from home to school. Move to a nearby river. At a distance of a meter, arm's length. Know something, feel something. on... ... Encyclopedic Dictionary

distance- I; Wed see also distance a) The space separating two points, two objects, etc., the gap between whom, than l. The shortest distance between two points. Distance from home to school. Move to a close distance... Dictionary of many expressions

GEOMETRY- a branch of mathematics that studies the properties of various figures (points, lines, angles, two-dimensional and three-dimensional objects), their sizes and relative positions. For ease of teaching, geometry is divided into planimetry and stereometry. IN… … Collier's Encyclopedia

Navigation*

Navigation- department of navigation (see), which contains a statement of methods for determining the position of a ship at sea, using a compass and log (see). To determine the place of a ship at sea means to plot on the map the point at which the ship is currently located.... ... Encyclopedic Dictionary F.A. Brockhaus and I.A. Ephron

COHEN- (Cohen) Hermann (1842 1918) German philosopher, founder and most prominent representative of the Marburg school of neo-Kantianism. Main works: 'Kant's Theory of Experience' (1885), 'Kant's Justification of Ethics' (1877), 'Kant's Justification of Aesthetics' (1889), 'Logic... ...

Kant Immanuel- Kant's life and writings Immanuel Kant was born in Konigsberg (now Kaliningrad) in East Prussia in 1724. His father was a saddler, and his mother a housewife; six of their children did not live to adulthood. Kant always remembered his parents from... ... Western philosophy from its origins to the present day

KANT'S CRITICAL PHILOSOPHY: THE TEACHING OF ABILITIES- (La philosophie critique de Kant: Doctrines des facultes, 1963) work by Deleuze. Characterizing the transcendental method in the introduction, Deleuze notes that Kant understands philosophy as the science of the relationship of all knowledge to essential goals... ... History of Philosophy: Encyclopedia

Farm principle- the basic principle of geometric optics (See Geometric optics). The simplest form of a f.p. is the statement that a ray of light always propagates in space between two points along a path along which its travel time is less than... Great Soviet Encyclopedia

Dijkstra's algorithm is a graph algorithm invented by the Dutch scientist Edsger Dijkstra in 1959. Finds the shortest paths from one of the vertices of the graph to all the others. The algorithm works only for graphs without edges of negative weight.

Let's consider the execution of the algorithm using the example of the graph shown in the figure.

Suppose you need to find the shortest distances from the 1st vertex to all the others.

The circles indicate the vertices, the lines indicate the paths between them (the edges of the graph). The numbers of the vertices are indicated in the circles, and their “price” is indicated above the edges - the length of the path. Next to each vertex there is a red mark - the length of the shortest path to this vertex from vertex 1.

First step. Let's look at the step of Dijkstra's algorithm for our example. Vertex 1 has the minimum label. Its neighbors are vertices 2, 3 and 6.

The first neighbor of vertex 1 is vertex 2, because the length of the path to it is minimal. The length of the path into it through vertex 1 is equal to the sum of the value of the label of vertex 1 and the length of the edge going from 1st to 2nd, that is, 0 + 7 = 7. This is less than the current label of vertex 2, infinity, so the new label is 2nd vertices is 7.

We perform a similar operation with two other neighbors of the 1st vertex - the 3rd and 6th.

All neighbors of vertex 1 are checked. The current minimum distance to vertex 1 is considered final and cannot be revised (that this is indeed the case was first proven by E. Dijkstra). Let's cross it out from the graph to mark that this vertex has been visited.

Second step. The algorithm step is repeated. Again we find the “nearest” of the unvisited vertices. This is vertex 2 with label 7.

Again we try to reduce the labels of the neighbors of the selected vertex, trying to pass through the 2nd vertex into them. The neighbors of vertex 2 are vertices 1, 3 and 4.

The first (in order) neighbor of vertex 2 is vertex 1. But it has already been visited, so we do nothing with the 1st vertex.

The next neighbor of vertex 2 is vertex 3, since it has the minimum label of the vertices marked as not visited. If you go to it through 2, then the length of such a path will be equal to 17 (7 + 10 = 17). But the current label of the third vertex is 9, which is less than 17, so the label does not change.

Another neighbor of vertex 2 is vertex 4. If you go to it through the 2nd, then the length of such a path will be equal to the sum of the shortest distance to the 2nd vertex and the distance between vertices 2 and 4, that is, 22 (7 + 15 = 22) . Since 22<, устанавливаем метку вершины 4 равной 22.

All neighbors of vertex 2 have been viewed, we freeze the distance to it and mark it as visited.

Third step. We repeat the algorithm step, selecting vertex 3. After “processing” it, we get the following results:

Next steps. We repeat the algorithm step for the remaining vertices. These will be vertices 6, 4 and 5, according to the order.

Completing the execution of the algorithm. The algorithm terminates when no more vertices can be processed. In this example, all vertices are crossed out, but it is a mistake to assume that this will be the case in any example - some vertices may remain uncrossed out if they cannot be reached, that is, if the graph is disconnected. The result of the algorithm is visible in the last figure: the shortest path from vertex 1 to 2 is 7, to 3 is 9, to 4 is 20, to 5 is 20, to 6 is 11.

Implementation of the algorithm in various programming languages:

C++

#include "stdafx.h" #include using namespace std; const int V=6; //Dijkstra's algorithm void Dijkstra(int GR[V][V], int st) ( int distance[V], count, index, i, u, m=st+1; bool visited[V]; for (i= 0; "< "<> "; cin>>start; Dijkstra(GR, start-1); system("pause>>void"); )

Pascal

program DijkstraAlgorithm; uses crt; const V=6; inf=100000; type vector=array of integer; var start: integer; const GR: array of integer=((0, 1, 4, 0, 2, 0), (0, 0, 0, 9, 0, 0), (4, 0, 0, 7, 0, 0), (0, 9, 7, 0, 0, 2), (0, 0, 0, 0, 0, 8), (0, 0, 0, 0, 0, 0)); (Dijkstra's algorithm) procedure Dijkstra(GR: array of integer; st: integer); var count, index, i, u, m, min: integer; distance: vector; visited: array of boolean; begin m:=st; for i:=1 to V do begin distance[i]:=inf; visited[i]:=false; end; distance:=0; for count:=1 to V-1 do begin min:=inf; for i:=1 to V do if (not visited[i]) and (distance[i]<=min) then begin min:=distance[i]; index:=i; end; u:=index; visited[u]:=true; for i:=1 to V do if (not visited[i]) and (GR<>0) and (distance[u]<>inf) and (distance[u]+GR inf then writeln(m," > ", i," = ", distance[i]) else writeln(m," > ", i," = ", "route unavailable"); end; (main block of the program) begin clrscr; write("Start vertex >> "); read(start); Dijkstra(GR, start); end.

Java

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.StringTokenizer; public class Solution ( private static int INF = Integer.MAX_VALUE / 2; private int n; //number of vertices in the digraph private int m; //number of arcs in the digraph private ArrayList adj; //adjacency list private ArrayList weight; //weight of edge in digraph private boolean used; //array for storing information about traversed and untraversed vertices private int dist; //array for storing the distance from the starting vertex //array of ancestors necessary to restore the shortest path from the starting vertex private int pred; int start; //starting vertex from which the distance to all other vertices is sought private BufferedReader cin; private PrintWriter cout; private StringTokenizer tokenizer; //procedure for launching Dijkstra's algorithm from the starting vertex private void dejkstra(int s) ( dist[s] = 0; //shortest distance to the starting vertex is 0 for (int iter = 0; iter< n; ++iter) { int v = -1; int distV = INF; //выбираем вершину, кратчайшее расстояние до которого еще не найдено for (int i = 0; i < n; ++i) { if (used[i]) { continue; } if (distV < dist[i]) { continue; } v = i; distV = dist[i]; } //рассматриваем все дуги, исходящие из найденной вершины for (int i = 0; i < adj[v].size(); ++i) { int u = adj[v].get(i); int weightU = weight[v].get(i); //релаксация вершины if (dist[v] + weightU < dist[u]) { dist[u] = dist[v] + weightU; pred[u] = v; } } //помечаем вершину v просмотренной, до нее найдено кратчайшее расстояние used[v] = true; } } //процедура считывания входных данных с консоли private void readData() throws IOException { cin = new BufferedReader(new InputStreamReader(System.in)); cout = new PrintWriter(System.out); tokenizer = new StringTokenizer(cin.readLine()); n = Integer.parseInt(tokenizer.nextToken()); //считываем количество вершин графа m = Integer.parseInt(tokenizer.nextToken()); //считываем количество ребер графа start = Integer.parseInt(tokenizer.nextToken()) - 1; //инициализируем списка смежности графа размерности n adj = new ArrayList[n]; for (int i = 0; i < n; ++i) { adj[i] = new ArrayList(); ) //initializing the list that stores the weights of the edges weight = new ArrayList[n]; for (int i = 0; i< n; ++i) { weight[i] = new ArrayList(); ) //read the graph specified by the list of edges for (int i = 0; i< m; ++i) { tokenizer = new StringTokenizer(cin.readLine()); int u = Integer.parseInt(tokenizer.nextToken()); int v = Integer.parseInt(tokenizer.nextToken()); int w = Integer.parseInt(tokenizer.nextToken()); u--; v--; adj[u].add(v); weight[u].add(w); } used = new boolean[n]; Arrays.fill(used, false); pred = new int[n]; Arrays.fill(pred, -1); dist = new int[n]; Arrays.fill(dist, INF); } //процедура восстановления кратчайшего пути по массиву предком void printWay(int v) { if (v == -1) { return; } printWay(pred[v]); cout.print((v + 1) + " "); } //процедура вывода данных в консоль private void printData() throws IOException { for (int v = 0; v < n; ++v) { if (dist[v] != INF) { cout.print(dist[v] + " "); } else { cout.print("-1 "); } } cout.println(); for (int v = 0; v < n; ++v) { cout.print((v + 1) + ": "); if (dist[v] != INF) { printWay(v); } cout.println(); } cin.close(); cout.close(); } private void run() throws IOException { readData(); dejkstra(start); printData(); cin.close(); cout.close(); } public static void main(String args) throws IOException { Solution solution = new Solution(); solution.run(); } }

Another option:

Import java.io.*; import java.util.*; public class Dijkstra ( private static final Graph.Edge GRAPH = ( new Graph.Edge("a", "b", 7), new Graph.Edge("a", "c", 9), new Graph.Edge( "a", "f", 14), new Graph.Edge("b", "c", 10), new Graph.Edge("b", "d", 15), new Graph.Edge("c ", "d", 11), new Graph.Edge("c", "f", 2), new Graph.Edge("d", "e", 6), new Graph.Edge("e", "f", 9), ); private static final String START = "a"; private static final String END = "e"; public static void main(String args) ( Graph g = new Graph(GRAPH); g.dijkstra (START); g.printPath(END); //g.printAllPaths()) ) class Graph ( private final Map graph; // mapping of vertex names to Vertex objects, built from a set of Edges /** One edge of the graph (only used by Graph constructor) */ public static class Edge ( public final String v1, v2; public final int dist; public Edge(String v1, String v2, int dist) ( this.v1 = v1; this.v2 = v2; this.dist = dist; ) ) /** One vertex of the graph, complete with mappings to neighboring vertices */ public static class Vertex implements Comparable ( public final String name; public int dist = Integer.MAX_VALUE; // MAX_VALUE assumed to be infinity public Vertex previous = null; public final Map neighbors = new HashMap<>(); public Vertex(String name) ( this.name = name; ) private void printPath() ( if (this == this.previous) ( System.out.printf("%s", this.name); ) else if ( this.previous == null) ( System.out.printf("%s(unreached)", this.name); ) else ( this.previous.printPath(); System.out.printf(" -> %s( %d)", this.name, this.dist); ) ) public int compareTo(Vertex other) ( return Integer.compare(dist, other.dist); ) ) /** Builds a graph from a set of edges * / public Graph(Edge edges) ( graph = new HashMap<>(edges.length); //one pass to find all vertices for (Edge e: edges) ( if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1)); if (!graph. containsKey(e.v2)) graph.put(e.v2, new Vertex(e.v2)) //another pass to set neighboring vertices for (Edge e: edges) ( graph.get(e.v1). neighbors.put(graph.get(e.v2), e.dist); //graph.get(e.v2).neighbors.put(graph.get(e.v1), e.dist); do this for an undirected graph ) ) /** Runs dijkstra using a specified source vertex */ public void dijkstra(String startName) ( if (!graph.containsKey(startName)) ( System.err.printf("Graph doesn"t contain start vertex \"%s\"\n", startName); return; ) final Vertex source = graph.get(startName); NavigableSet q = new TreeSet<>(); // set-up vertices for (Vertex v: graph.values()) ( v.previous = v == source ? source: null; v.dist = v == source ? 0: Integer.MAX_VALUE; q.add( v); ) dijkstra(q); ) /** Implementation of dijkstra's algorithm using a binary heap. */ private void dijkstra(final NavigableSet q) ( Vertex u, v; while (!q.isEmpty()) ( u = q.pollFirst(); // vertex with shortest distance (first iteration will return source) if (u.dist == Integer.MAX_VALUE) break; // we can ignore u (and any other remaining vertices) since they are unreachable //look at distances to each neighbor for (Map.Entry a: u.neighbours.entrySet()) ( v = a.getKey(); //the neighbor in this iteration final int alternateDist = u.dist + a.getValue(); if (alternateDist< v.dist) { // shorter path to neighbour found q.remove(v); v.dist = alternateDist; v.previous = u; q.add(v); } } } } /** Prints a path from the source to the specified vertex */ public void printPath(String endName) { if (!graph.containsKey(endName)) { System.err.printf("Graph doesn"t contain end vertex \"%s\"\n", endName); return; } graph.get(endName).printPath(); System.out.println(); } /** Prints the path from the source to every vertex (output order is not guaranteed) */ public void printAllPaths() { for (Vertex v: graph.values()) { v.printPath(); System.out.println(); } } }

C

#include #include #include //#define BIG_EXAMPLE typedef struct node_t node_t, *heap_t; typedef struct edge_t edge_t; struct edge_t ( node_t *nd; /* target of this edge */ edge_t *sibling;/* for singly linked list */ int len; /* edge cost */ ); struct node_t ( edge_t *edge; /* singly linked list of edges */ node_t *via; /* where previous node is in shortest path */ double dist; /* distance from originating node */ char name; /* the, er , name */ int heap_idx; /* link to heap position for updating distance */ ); /* --- edge management --- */ #ifdef BIG_EXAMPLE # define BLOCK_SIZE (1024 * 32 - 1) #else # define BLOCK_SIZE 15 #endif edge_t *edge_root = 0, *e_next = 0; /* Don't mind the memory management stuff, they are besides the point. Pretend e_next = malloc(sizeof(edge_t)) */ void add_edge(node_t *a, node_t *b, double d) ( if (e_next == edge_root ) ( edge_root = malloc(sizeof(edge_t) * (BLOCK_SIZE + 1)); edge_root.sibling = e_next; e_next = edge_root + BLOCK_SIZE; ) --e_next->nd = b; ->sibling = a->edge; a->edge = e_next; ) void free_edges() ( for (; edge_root; edge_root = e_next) ( e_next = edge_root.sibling; free(edge_root); ) ) /* --- priority queue stuff --- */ heap_t *heap; void set_dist(node_t *nd, node_t *via, double d) ( int i, j; /* already knew better path */ if (nd->via && d >= nd->dist) return; /* find existing heap entry, or create a new one */ nd->dist = d; nd->via = via; i = ++heap_len; /* upheap */ for (; i > 1 && nd->dist< heap->dist; i = j) (heap[i] = heap[j])->heap_idx = i; heap[i] = nd; nd->heap_idx = i; ) node_t * pop_queue() ( node_t *nd, *tmp; int i, j; if (!heap_len) return 0; /* remove leading element, pull tail element there and downheap */ nd = heap; tmp = heap; for (i = 1; i< heap_len && (j = i * 2) <= heap_len; i = j) { if (j < heap_len && heap[j]->dist > heap->dist) j++; if (heap[j]->dist >= tmp->dist) break; (heap[i] = heap[j])->heap_idx = i; ) heap[i] = tmp; tmp->heap_idx = i; return nd; ) /* --- Dijkstra stuff; unreachable nodes will never make into the queue --- */ void calc_all(node_t *start) ( node_t *lead; edge_t *e; set_dist(start, start, 0); while ((lead = pop_queue())) for (e = lead->edge; e; e = e->sibling) set_dist(e->nd, lead, lead->dist + e->len ) void show_path(node_t *nd) ( if (nd->via == nd) printf( "%s", nd->name); else if (!nd->via) printf("%s(unreached)", nd->name); else ( show_path(nd->via); printf("- > %s(%g) ", nd->name, nd->dist); ) ) int main(void) ( #ifndef BIG_EXAMPLE int i; # define N_NODES ("f" - "a" + 1) node_t * nodes = calloc(sizeof(node_t), N_NODES); for (i = 0; i< N_NODES; i++) sprintf(nodes[i].name, "%c", "a" + i); # define E(a, b, c) add_edge(nodes + (a - "a"), nodes + (b - "a"), c) E("a", "b", 7); E("a", "c", 9); E("a", "f", 14); E("b", "c", 10);E("b", "d", 15);E("c", "d", 11); E("c", "f", 2); E("d", "e", 6); E("e", "f", 9); # undef E #else /* BIG_EXAMPLE */ int i, j, c; # define N_NODES 4000 node_t *nodes = calloc(sizeof(node_t), N_NODES); for (i = 0; i < N_NODES; i++) sprintf(nodes[i].name, "%d", i + 1); /* given any pair of nodes, there"s about 50% chance they are not connected; if connected, the cost is randomly chosen between 0 and 49 (inclusive! see output for consequences) */ for (i = 0; i < N_NODES; i++) { for (j = 0; j < N_NODES; j++) { /* majority of runtime is actually spent here */ if (i == j) continue; c = rand() % 100; if (c < 50) continue; add_edge(nodes + i, nodes + j, c - 50); } } #endif heap = calloc(sizeof(heap_t), N_NODES + 1); heap_len = 0; calc_all(nodes); for (i = 0; i < N_NODES; i++) { show_path(nodes + i); putchar("\n"); } #if 0 /* real programmers don"t free memories (they use Fortran) */ free_edges(); free(heap); free(nodes); #endif return 0; }

PHP

$edge, "cost" => $edge); $neighbors[$edge] = array("end" => $edge, "cost" => $edge); ) $vertices = array_unique($vertices); foreach ($vertices as $vertex) ( $dist[$vertex] = INF; $previous[$vertex] = NULL; ) $dist[$source] = 0; $Q = $vertices; while (count($Q) > 0) ( // TODO - Find faster way to get minimum $min = INF; foreach ($Q as $vertex)( if ($dist[$vertex]< $min) { $min = $dist[$vertex]; $u = $vertex; } } $Q = array_diff($Q, array($u)); if ($dist[$u] == INF or $u == $target) { break; } if (isset($neighbours[$u])) { foreach ($neighbours[$u] as $arr) { $alt = $dist[$u] + $arr["cost"]; if ($alt < $dist[$arr["end"]]) { $dist[$arr["end"]] = $alt; $previous[$arr["end"]] = $u; } } } } $path = array(); $u = $target; while (isset($previous[$u])) { array_unshift($path, $u); $u = $previous[$u]; } array_unshift($path, $u); return $path; } $graph_array = array(array("a", "b", 7), array("a", "c", 9), array("a", "f", 14), array("b", "c", 10), array("b", "d", 15), array("c", "d", 11), array("c", "f", 2), array("d", "e", 6), array("e", "f", 9)); $path = dijkstra($graph_array, "a", "e"); echo "path is: ".implode(", ", $path)."\n";


Python

from collections import namedtuple, queue from pprint import pprint as pp inf = float("inf") Edge = namedtuple("Edge", "start, end, cost") class Graph(): def __init__(self, edges): self .edges = edges2 = self.vertices = set(sum(( for e in edges2, )) def dijkstra(self, source, dest): assert source in self.vertices dist = (vertex: inf for vertex in self.vertices ) previous = (vertex: None for vertex in self.vertices) dist = 0 q = self.vertices.copy() neighbors = (vertex: set() for vertex in self.vertices) for start, end, cost in self. edges: neighbors.add((end, cost)) #pp(neighbors) while q: u = min(q, key=lambda vertex: dist) q.remove(u) if dist[u] == inf or u = = dest: break for v, cost in neighbors[u]: alt = dist[u] + cost if alt< dist[v]: # Relax (u,v,a) dist[v] = alt previous[v] = u #pp(previous) s, u = deque(), dest while previous[u]: s.pushleft(u) u = previous[u] s.pushleft(u) return s graph = Graph([("a", "b", 7), ("a", "c", 9), ("a", "f", 14), ("b", "c", 10), ("b", "d", 15), ("c", "d", 11), ("c", "f", 2), ("d", "e", 6), ("e", "f", 9)]) pp(graph.dijkstra("a", "e")) Output: ["a", "c", "d", "e"]

The path along the dotted line in the picture is shorter than the path along the solid one. And now a little more detail using the example of sea routes:

If you sail on a constant course, then the trajectory of the ship’s movement along the earth’s surface will be a curve, called in mathematics logarithmicspiral.

In navigation, this complex line of double curvature is called rhoxodrome, which translated from Greek means “oblique running.”

However, the shortest distance between two points on the globe is measured along the arc of a great circle.

The arc of a great circle is obtained as a trace from the intersection of the earth's surface with a plane passing through the center of the earth, taken as a sphere.

In navigation, the great circle arc is called orthodromy, which translated means “straight running.” The second feature of orthodromy is that it intersects the meridians at different angles (Fig. 29).

The difference in distances between two points on the earth's surface according to loxodrome and orthodrome is of practical importance only during large ocean crossings.

Under normal conditions, this difference is neglected and swimming is performed on a constant course, i.e. by rhoxodrome.

To derive the equation, let's take the rhoxodrome (Fig. 30, A) two points A And IN, the distance between them is simply small. Drawing meridians and a parallel through them, we obtain an elementary right-angled spherical triangle ABC. In this triangle, the angle formed by the intersection of the meridian and the parallel is right, and the angle PnAB equal to the ship's heading K. Katet AC represents a segment of the meridian arc and can be expressed

Where R - radius of the Earth taken as a sphere;

Δφ - elementary increment of latitude (difference in latitude).

Leg NE represents a parallel arc segment

where r - parallel radius;

Δλ - elementary difference in longitude.

From triangle OO 1 C one can find that

Then in the final form the legs NE can be expressed like this:

Taking an elementary spherical triangle ABC for flat, we'll write

After reduction R and replacing elementary small increments of coordinates with infinitesimal ones we will have

Let's integrate the resulting expression in the range from φ 1, λ 1 to φ 2, λ 2 considering the tgK value to be constant:

On the right side we have a table integral. After substituting its value, we obtain the equation of loxodromy on a ball

Analysis of this equation allows us to draw the following conclusions:

At courses of 0 and 180°, the loxodrome turns into an arc of a great circle - a meridian;

At courses of 90 and 270°, the rhoxodrome coincides with the parallel;

A loxodrome crosses each parallel only once, but each meridian an infinite number of times. those. spiraling towards the pole, it does not reach it.

Sailing on a constant course, i.e., along the rhoxodrome, although it is not the shortest distance between two points on Earth, represents significant convenience for the navigator.

The requirements for a marine navigation chart can be formulated based on the advantage of sailing along the rhoxodrome and the results of analyzing its equation as follows.

1. A loxodrome, crossing the meridians at a constant angle, should be depicted as a straight line.

2. The cartographic projection used to construct maps must be equiangular so that the courses, bearings and angles on it correspond to their meaning on the ground.

3. Meridians and parallels, like course lines of 0, 90, 180° and 270°, must be mutually perpendicular straight lines.

The shortest distance between two given points on the surface of the Earth, taken as a sphere, is the smaller of the arcs of the great circle passing through these points. Except in the case of a ship following a meridian or equator, an orthodrome intersects the meridians at different angles. Therefore, a ship following such a curve must constantly change its course. In practice, it is more convenient to follow a course that makes a constant angle with the meridians and is depicted on the map in the Mercator projection by a straight line - a rhoxodrome. However, at large distances the difference in the length of the orthodrome and the loxodrome reaches a significant value. Therefore, in such cases, the orthodrome is calculated and intermediate points are marked on it, between which they sail along the loxodrome.

A cartographic projection that satisfies the above requirements was proposed by the Dutch cartographer Gerard Cramer (Mercator) in 1569. In honor of its creator, the projection was named Mercatorian

And who wants to learn even more interesting information, find out more The original article is on the website InfoGlaz.rf Link to the article from which this copy was made -

(Descriptive geometry)
  • CD (CXDX, C2D2) depicted as a point C5 = D5 A5B5 equals...
    (Descriptive geometry)
  • Determining the distance between two parallel planes
    Determining the distance between two parallel planes in general position 01| X It is convenient to reduce it to the problem of determining the distance between the same two planes, transformed into the position of the projectors. In this case, the distance between the planes will be determined as the perpendicular between the lines...
    (Descriptive geometry)
  • Determining the distance between two intersecting lines
    If you need to determine the shortest distance between two intersecting straight lines, you have to change the projection plane systems twice. When solving this problem, the straight line CD (CXDX, C2D2) depicted as a point C5 = D5(Fig. 198). Distance from this point to the projection A5B5 equals...
    (Descriptive geometry)
  • Angle between two intersecting straight lines
    This is the angle between two intersecting lines parallel to the data. Thus, this task is similar to the previous one. To solve it, you need to take an arbitrary point and draw two lines through it, parallel to the given intersecting lines, and using the transformation of projections, determine the desired angle....
    (Fundamentals of descriptive geometry. Short course and collection of problems.)
  • Determining the distance between two parallel lines
    The problem is solved by the method of double replacement of projection planes. At the final stage, one of the projection planes must be perpendicular to one of the intersecting lines. Then the shortest distance between them is determined by the size of the perpendicular segment to the other crossing line (Fig. 199)....
    (Descriptive geometry)
  • Share: