
Доставка пиццы
Вы с друзьями решили запустить стартап по Доставке Пиццы. Рецепты составили, поставщиков ресурсов нашли, в аренду помещения взяли, поваров наняли.
Осталось дело за разработкой алгоритма, который будет находить кратчайший путь от Кухни вашей Пиццерии до клиентов.
У вас есть база данных дорог города, заданной массивом координат перекрестков и связей дорог.
Данные:

1. И пусть весь мир подождёт
Первый спринт разработки. Для начала определитесь с форматом хранения базы данных дорог. Научитесь считывать сырые данные и складывать в удобный для вашего алгоритма формат.
Код для считывания графа из файла
Это лишь небольшой шаблон того, с чего можно начать, при желании доработайте его под свои нужды
Файл Node.java
public class Node {
private final long id;
private final double lon;
private final double lat;
private double x;
private double y;
public Node(long id, double lon, double lat) {
this.id = id;
this.lon = lon;
this.lat = lat;
}
public long getId() {
return id;
}
public double getLon() {
return lon;
}
public double getLat() {
return lat;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
Файл Edge.java
public class Edge {
private final long u;
private final long v;
private double ux;
private double uy;
private double vx;
private double vy;
private long distance; // расстояние между u-v
public Edge(long u, long v) {
this.u = u;
this.v = v;
}
public long getU() {
return u;
}
public long getV() {
return v;
}
public double getUx() {
return ux;
}
public void setUx(double ux) {
this.ux = ux;
}
public double getUy() {
return uy;
}
public void setUy(double uy) {
this.uy = uy;
}
public double getVx() {
return vx;
}
public void setVx(double vx) {
this.vx = vx;
}
public double getVy() {
return vy;
}
public void setVy(double vy) {
this.vy = vy;
}
public long getDistance() {
return distance;
}
public void setDistance(long distance) {
this.distance = distance;
}
}
Тут мы инкапсулируем считывание данных из файла. Напоминаю, это только шаблон, feel free to доработать этот код под себя, изменить или вообще написать совсем по-своему.
Файл MapFileReaderUtils.java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MapFileReaderUtils {
public static List<Node> readNodes(String filePath) throws IOException {
List<Node> nodes = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line = br.readLine();
while ((line = br.readLine()) != null) {
if (line.isEmpty()) {
continue;
}
String[] cells = line.split(",");
if (cells.length >= 3) {
long id = Long.parseLong(cells[0].trim());
double lon = Double.parseDouble(cells[1].trim());
double lat = Double.parseDouble(cells[2].trim());
nodes.add(new Node(id, lon, lat));
}
}
}
return nodes;
}
public static List<Edge> readEdges(String filePath) throws IOException {
List<Edge> edges = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line = br.readLine();
while ((line = br.readLine()) != null) {
if (line.isEmpty()) {
continue;
}
String[] cells = line.split(",");
if (cells.length >= 2) {
long u = Long.parseLong(cells[0].trim());
long v = Long.parseLong(cells[1].trim());
edges.add(new Edge(u, v));
}
}
}
return edges;
}
}
Файл DistanceUtils.java
Допустим, вынесем вычисление дистанций вот так
import java.util.*;
public class DistanceUtils {
public static double euclideanDistance(double x1, double y1, double x2, double y2) {
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y1 - y2, 2));;
}
}
Main.java
Что-то вроде такого
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Node> nodes = MapFileReaderUtils.readNodes("omsk/nodes.csv");
List<Edge> edges = MapFileReaderUtils.readEdges("omsk/edges.csv");
Map<Long, Integer> nodePositionsByNodeId = new HashMap<>();
for (int i = 0; i < nodes.size(); i++) {
nodePositionsByNodeId.put(nodes.get(i).getId(), i);
}
for (Edge edge : edges) {
Node u = nodes.get(nodePositionsByNodeId.get(edge.getU()));
Node v = nodes.get(nodePositionsByNodeId.get(edge.getV()));
edge.setUx(u.getX());
edge.setUy(u.getY());
edge.setVx(v.getX());
edge.setVy(v.getY());
edge.setDistance(DistanceUtils.euclideanDistance(edge.getUx(), edge.getUy(), edge.getVx(), edge.getVy()));
}
}
}
Далее реализуйте алгоритм Дейкстры для поиска пути.
Сделайте отдельный интерфейс RouteBuilder примерно такого вида
import java.util.List;
public interface RouteBuilder {
List<Edge> createRoute(Node start, Node finish);
}
Под реализацию Дейкстры сделайте класс DijkstraRouteBuilder, реализующий этот интерфейс, с реализацией алгоритма.
2. Чтобы стоять на месте нужно бежать со всех ног
Отдел поддержки собщает, что доставка не улкадывается в срок "доставить пиццу н за неделю". И проблема не в доставщиках пиццы и не в кухне, а в алгоритме поиска пути. Его надо ускорить!
Реализуйте алгоритм А* для поиска пути.
Под реализацию A* сделайте класс AStarRouteBuilder, реализующий интерфейс RouteBuilder, с реализацией алгоритма.
3. To See the World...
Пользователи хотят видеть маршрут, по которому к ним поедет доставщик.
Реализуйте визуализацию вашего алгоритма. Используйте для этого библиотеку libGDX.
Есть описание создания простого проекта с этой библиотекой вот здесь, тут есть небольшие туториалы. Помимо туториалов (не только этих) воспользуйтесь нейронками, 2026 год как-никак Sadge.
Всякие материалы по дорогам и картам
- OSMNX - визуализация и загрузка графов дорог на питоне
- OSMNX туториал
- Open Street Maps