Thu t toán Dijkstra ậ Thuật toán Dijkstra là một thuật toán tìm đường đi ngắn nhất trong một đồ thị có hướng và trọng số.. Nó được sử dụng để tìm đường đi từ một đỉnh đầu tiên đến một đỉ
ĐỒ THỊ VÀ CÁC THUẬT TOÁN
Các Khái Ni m ệ
Thuật toán Dijkstra là phương pháp tối ưu để tìm đường đi ngắn nhất trong đồ thị có hướng và trọng số Thuật toán này giúp xác định lộ trình từ một đỉnh khởi đầu đến một đỉnh đích trong đồ thị, dựa trên các trọng số của các cạnh.
Lịch sử thuật toán Dijkstra
Thuật toán Dijkstra, được phát triển bởi Edsger W Dijkstra vào năm 1959, là một phương pháp tìm đường đi ngắn nhất từ một đỉnh đến tất cả các đỉnh còn lại trong đồ thị có trọng số Ban đầu áp dụng trong các mô hình lý thuyết cho máy tính, thuật toán này đã nhanh chóng được sử dụng rộng rãi trong nhiều lĩnh vực như vận tải, mạng lưới, và định tuyến Ngày nay, Dijkstra được xem là một trong những thuật toán quan trọng nhất trong lĩnh vực tìm đường đi.
- Tìm đường đi ngắn nhất trên bản đồ
- Ứng dụng trong mạng xã hộitrong hệ thống thông tin di động
- Ứng dụng trong hàng không
Mô tả thuật toán Dijkstra Đầu vào:
Đồ thị có trọng số dương được biểu diễn qua danh sách kề, ma trận kề hoặc các cấu trúc dữ liệu khác, trong đó mỗi cạnh mang một trọng số không âm.
- Đỉnh nguồn: Đỉnh xuất phát từ đó bạn muốn tìm đường đi ngắn nhất
Gán giá trị vô cùng lớn (hoặc giá trị đặc biệt) cho tất cả các đỉnh ngoại trừ đỉnh nguồn, gán giá trị 0 cho đỉnh nguồn
Bước 2: Lặp cho đến khi tất cả các đỉnh đều được xét
- Chọn đỉnh v có giá trị nhỏ nhất từ những đỉnh chưa xét
- Duyệt qua tất cả các đỉnh kề của v.
- N u giá tr hi n t i cế ị ệ ạ ủa đỉnh k lề ớn hơn giá trị hi n t i c a v c ng vệ ạ ủ ộ ới trọng s cố ủa cạnh (v, kề), thì cập nhật giá tr cị ủa đỉnh kề
Sau khi l p qua t t cặ ấ ả các đỉnh, b n s có giá tr ng n nh t tạ ẽ ị ắ ấ ừ đỉnh nguồn đến t t cấ ả các đỉnh khác Độ ph c tạp thời gian ứ
Độ phức tạp thời gian của thuật toán Dijkstra phụ thuộc vào cách cài đặt và biểu diễn đồ thị Trong trường hợp tốt nhất, độ phức tạp có thể đạt O((V + E) log V), với V là số đỉnh và E là số cạnh của đồ thị.
1.1.2.1 Khái niệm đồ thị Đồ th là một d ng bi u di n c a m t t p hị ạ ể ễ ủ ộ ậ ợp các đối tượng, trong đó các cặp đối tượng thường được kết nối bằng các liên kết Các đối tượng liên k t vế ới nhau được đại di n bệ ởi các điểm được gọi là "đỉnh" (node), trong khi các liên kết kết nối chúng được gọi là "cạnh" (edges) Cụ thể, các thành ph n trong mầ ột đồ thị được xác định như sau:
Hình 1: Ví d vụ ề đồ thị
Đỉnh (Node) trong đồ thị là các điểm đại diện cho các đối tượng trong mô hình Mỗi đỉnh được gán một tên hoặc định danh duy nhất để phân biệt với những đỉnh khác.
Cạnh (Edge) trong đồ thị là các liên kết giữa hai đỉnh, thể hiện mối quan hệ giữa các đối tượng tương ứng Cạnh có thể có hướng, cho phép xác định thứ tự từ đỉnh này đến đỉnh khác, hoặc không có hướng, thể hiện mối quan hệ tương đối giữa các đỉnh.
- Biể u di ễn đồ thị ằ b ng ma tr ận:
Đồ thị vô hướng là một loại đồ thị mô tả mối quan hệ giữa các đỉnh mà không phân biệt hướng đi Cụ thể, nếu có một cạnh nối giữa đỉnh A và đỉnh B, cạnh này được xem là vô hướng, cho phép di chuyển từ A đến B hoặc ngược lại mà không cần quan tâm đến hướng di chuyển.
Cấu Trúc và Cài Đặt
Đồ thị có hướng là loại đồ thị trong đó mỗi cạnh được gán một hướng cụ thể Điều này có nghĩa là khi di chuyển từ một đỉnh này đến một đỉnh khác qua một cạnh, hướng của cạnh sẽ quyết định hướng di chuyển.
Trong đồ thị hỗn hợp (mixed graph), bậc của đỉnh là một yếu tố quan trọng phản ánh cấu trúc của đồ thị Đồ thị hỗn hợp bao gồm cả các cạnh vô hướng, cho phép di chuyển hai chiều, và các cạnh có hướng, chỉ cho phép di chuyển một chiều Sự kết hợp này tạo nên sự đa dạng trong cách thức kết nối và tương tác giữa các đỉnh trong đồ thị.
1.2 Cấ Trúc và Cài Đặt u
The Dijkstra algorithm begins by initializing a distance map and creating a priority queue, Q Each vertex, v, in the graph is assigned an initial distance of INFINITY and an undefined previous value, before being added to Q The distance for the starting vertex is set to 0 The algorithm then processes the queue, repeatedly removing the vertex, u, with the smallest distance For each neighbor, v, of u, it calculates an alternative distance, alt, and updates the distance and previous values if this new distance is smaller The process continues until all vertices have been evaluated, ultimately returning the distance and previous maps.
Cài đặt thuật toán trong C#:
17 using System; public class DistOriginal { publicint distance; publicint parentVert; public DistOriginal(int pv, int d) { distance = d; parentVert = pv;
}} public class Vertex { publicstring label; publicbool isInTree; public Vertex(string lab) { label = lab; isInTree = false;
}} public class Graph { private constint maxVerts = 20;
Vertex[] vertexList; int[, ] adjMat; int nVerts; int nTree;
DistOriginal[] sPath; int currentVert; int startToCurrent; public Graph() { vertexList = new Vertex[maxVerts]; adjMat = newint[maxVerts, maxVerts]; nVerts = 0; nTree = 0; for (int j = 0; j < maxVerts; j++) { for (int k = 0; k < maxVerts; k++) { adjMat[j, k] = infinity;
} public void AddVertex(string lab) { vertexList[nVerts] = new Vertex(lab); nVerts++;
} public void AddEdge(int start, int theEnd, int weight) { adjMat[start, theEnd] = weight;
} public void Path() { int startTree = 0; vertexList[startTree].isInTree = true; nTree = 1; for (int j = 0; j < nVerts; j++) { int tempDist = adjMat[startTree, j]; sPath[j] = new DistOriginal(startTree, tempDist);
} while (nTree < nVerts) { int indexMin = GetMin(); int minDist = sPath[indexMin].distance; currentVert = indexMin; startToCurrent = sPath[indexMin].distance; vertexList[currentVert].isInTree = true; nTree++;
102 nTree = 0; for (int j = 0; j < nVerts; j++) { vertexList[j].isInTree = false;
} publicint GetMin() { int minDist = infinity; int indexMin = 0; for (int j = 1; j < nVerts; j++) {
(!(vertexList[j].isInTree) && sPath[j].distance < minDist) { if minDist = sPath[j].distance; indexMin = j;
} public void AdjustShortPath() { int column = 1; while (column < nVerts) {
(vertexList[column].isInTree) { if column++;
} else { int currentToFringe = adjMat[currentVert, column]; int startToFringe = startToCurrent + currentToFringe; int sPathDist = sPath[column].distance;
(startToFringe < sPathDist) { if sPath[column].parentVert = currentVert; sPath[column].distance = startToFringe;
}}} public void DisplayPaths() { for (int j = 0; j < nVerts; j++) {
Console.Write(sPath[j].distance); string parent = vertexList[sPath[j].parentVert].label;
Cài đặ ớp đỉ t l nh Vertex:
8 public class Vertex { public bool wasVisited; public string label; public Vertex(string label) { this.label = label; wasVisited = false;
Biểu di n các c nh Edge: ễ ạ
In this code snippet, an array of four vertices is created, with vertices labeled "A," "B," "C," and "D" added sequentially The variable `nVertices` is incremented after each addition to track the total number of vertices An adjacency matrix is then initialized to represent the connections between these vertices, where a value of 1 indicates a connection; for example, vertices "A" and "B" are connected, as are "B" and "C."
Cài đặ ớp đồ t l thị (Grapth):
18 public class Graph { private int NUM_VERTICES; private Vertex[] vertices; private int[, ] adjMatrix; private int numVerts; public Graph(int numberOfVertices) {
NUM_VERTICES = numberOfVertices; vertices = new Vertex[NUM_VERTICES]; adjMatrix = newint[NUM_VERTICES, NUM_VERTICES]; numVerts = 0; for (int j = 0; j < NUM_VERTICES; j++) { for (int k = 0; k < NUM_VERTICES; k++) { adjMatrix[j, k] = 0;
}}} public void AddVertex(string label) { vertices[numVerts] = new Vertex(label); numVerts++;
So sánh thu t toán Dijkstra, Warshall và Bellman - Ford ậ
31 public void AddEdge(int start, int end) { adjMatrix[start, end] = 1; adjMatrix[end, start] = 1;
}} public class Vertex { public string label; public Vertex(string lab) { label = lab;
1.3 So sánh thu t toán ậ tìm đường đi ngắ n nh t Dijkstra, Warshall và ấ Bellman - Ford Đặc điểm Dijkstra Warshall Bellman-Ford
Tìm đường đi ngắn nh t t m ấ ừ ột đỉnh đến t t c ấ ả các đỉ nh còn l ại trong đồ thị có tr ng ọ số
Tìm đường đi ng n nh t gi ắ ấ ữa t t c các c p ấ ả ặ đỉnh trong đồ thị có tr ng s ọ ố
Tìm đường đi ngắn nh t t m ấ ừ ột đỉnh đến t t c ấ ả các đỉ nh còn l ại trong đồ thị có tr ng ọ số Ưu điểm Nhanh, hi u qu v ệ ả ới đồ th ị thưa
Hiệu quả v ới đồ thị dày
Có th x ể ử lý đồ thị có cạnh có tr ng s ọ ố âm Nhược điểm
Chỉ có th x ể ử lý đồ thị có cạnh có trọng số không âm
Không hi u qu ệ ả với đồ thị thưa
Có thể chạ y nhi u ề vòng lặp hơn thuật toán Dijkstra Cài đặt
Dễ dàng, chỉ c n m ầ ột vòng lặp
Phức tạp hơn thuật toán Dijkstra
Phức t ạp hơn thuậ t toán Dijkstra Ứng dụng
Tính toán đường đi ng n nh t trong m ng ắ ấ ạ giao thông
Tính toán đườ ng đi ngắn nhất trong mạng lưới điện
Tính toán đường đi ng n nh t trong m ng ắ ấ ạ lưới bán lẻ
PHÂN TÍCH VÀ THIẾT KẾ LỚP
Phân tích bài toán tối ưu chi phí vận tải bằng thuật toán Dijkstra
Ứng dụng này được thiết kế để tìm kiếm lộ trình tối ưu cho việc vận chuyển hàng hóa từ điểm A đến điểm X với chi phí thấp nhất, dựa trên những dữ liệu chi phí vận tải đã được tính toán trước giữa các địa điểm trong quốc gia.
Để phát triển một ứng dụng tối ưu hóa chi phí vận tải, cần xây dựng một đồ thị có trọng số với các đỉnh đại diện cho các địa điểm trong quốc gia, chẳng hạn như Sài Gòn và Đồng Nai, cùng với chi phí di chuyển trên mỗi quãng đường.
Thuật toán: Sử dụng thuật toán Dijkstra để tìm đường đi ngắn nhất giữa hai địa điểm (đỉnh)
Trong bài toán tìm đường đi ngắn nhất, chi phí vận chuyển được xem như quãng đường giữa hai địa điểm Tuy nhiên, để tối ưu hóa chi phí vận chuyển hàng hóa, cần tuân thủ các quy định cụ thể trong quá trình tính toán.
Các yếu tố ảnh hưởng đến chi phí vận chuyển:
Giá xăng hiện tại sẽ ảnh hưởng đến chi phí di chuyển, giả sử để đi 100km, xe sẽ tiêu tốn khoảng 10 lít xăng Mức giá mỗi lít xăng sẽ được điều chỉnh theo từng thời điểm.
Tạo lớp Province để lưu trữ thông tin về mỗi địa điểm, bao gồm tên tỉnh (provinceName), tên đỉnh tương ứng (verticesName) và tọa độ của tỉnh (verticesLocation).
Tạo lớp Vertex để quản lý thông tin của từng đỉnh trong đồ thị, bao gồm các thuộc tính như nameVertices để lưu tên đỉnh, wasVisited để xác định trạng thái (đã thăm hoặc chưa thăm), previousVertices để lưu trữ đỉnh cha trực tiếp, và pathLength để ghi lại khoảng cách từ đỉnh nguồn đến đỉnh hiện tại.
Hàng đợi ưu tiên PriorityQueueForGraph:
Ta tạo lớp NodePriorityQueue và lớp PriorityQueueForGraph để hỗ trợ cho thuật toán Dijkstra bao gồm:
Lớp này đại diện cho một nút trong hàng đợi ưu tiên
The attributes include: distance, which measures the distance from the source vertex to the current vertex; verticesIndex, which indicates the index of the current vertex; and next, which references the subsequent node.
Constructor (hàm tạo) khởi tạo các giá trị cho distance, verticesIndex, và thiết lập next thành null
Lớp này đại diện cho một hàng đợi ưu tiên cho đồ thị
Front: tham chiếu đến node phía trước của hàng đợi ưu tiên
Constructor (hàm tạo) khởi tạo front thành null, cho biết hàng đợi ưu tiên là trống Enqueue: chèn node
IsEmpty: xem hàng đợi ưu tiên có trống hay không
GetVerticesIndexFront: trả về chỉ số của node có độ ưu tiên cao nhất
GetDistanceFront: trả về khoảng cách của đỉnh nguồn tới đỉnh được lưu trong node có độ ưu tiên cao nhất
Dequeue: Xóa node có độ ưu tiên cao nhất
We create a Graph class to implement Dijkstra's algorithm for optimizing transportation costs The class includes attributes such as 'adjacency', which is an adjacency matrix storing the distances between two vertices; 'adjacencyVertices', a list that contains the neighboring vertices for each vertex; and 'vertices', which is a list of all vertices in the graph.
GetIndex: Lấy chỉ số của đỉnh trong danh sách đỉnh
Dijkstra: Thuật toán tìm đường đi ngắn nhất
PathInformation: Thể hiện thông tin các đỉnh trong đường đi ngắn nhất Cách gi i quy t bài toán: ả ế
Bài toán: Tìm đường đi ngắn nh t theo thu t toán Dijkstra ấ ậ
Bước 1: Từ đỉnh g c, khi tính toán khoảng cách tới chính nó là 0, khoảng cách từ đỉnh này tới các đỉnh khác là +∞, ta có danh sách các khoảng cách tới các đỉnh Bước 2: Chọn đỉnh A có khoảng cách nhỏ nhất trong danh sách và đánh dấu là đã xét, các lần sau sẽ không xem xét đỉnh này nữa.
Bước 3: Xem xét từng đỉnh kề B của đỉnh A Nếu khoảng cách từ đỉnh gốc đến đỉnh B nhỏ hơn khoảng cách hiện tại đang được ghi nhận, cần cập nhật giá trị khoảng cách và đỉnh A vào khoảng cách hiện tại của B.
Bước 4: Sau khi kiểm tra tất cả các đỉnh của A, chúng ta sẽ có danh sách khoảng cách tới các điểm đã được cập nhật Tiếp theo, lặp lại Bước 2 với danh sách này cho đến khi tìm được khoảng cách ngắn nhất tới tất cả các đỉnh.
Sau khi giải quyết bài toán tổng quát, chúng ta có thể tìm được đường đi ngắn nhất từ A đến L với khoảng cách 263 km Cụ thể, trong bản đồ tỉnh miền Bắc, đường đi ngắn nhất từ Hà Giang đến Bắc Giang là qua Lạng Sơn, với tổng chiều dài 263 km.
● Lớp NodePriorityQueue và PriorityQueueForGraph hỗ trợ cho thuật toán Dijkstra
The NodePriorityQueue class is designed to manage nodes in a priority queue, featuring properties for distance and vertex index Each node contains a double value for distance, an integer for the vertex index, and a reference to the next node in the queue The constructor initializes these properties, setting the distance and vertex index while linking to the next node as null.
}} public classPriorityQueueForGraph{ private NodePriorityQueue front; publicPriorityQueueForGraph(){ front = null;
} public void Enqueue(double distance, int verticesIndex) {
NodePriorityQueue newNode = new NodePriorityQueue(distance, verticesIndex);
// Nếu hàng đợi tr ng ho c ố ặ đỉnh có độ ư u ti n cao h n nh ê ơ đỉ đầu tiên
(front == if null || distance < front.distance){
57 newNode.next = front; front = newNode;
// Tìm nh có đỉ độ u tiư ên cao h n ơ đểchèn sau đó while (current.next != null && distance > current.next.distance){ current = current.next;
} newNode.next = current.next; current.next = newNode;
(front == if null){ return true;
} public int GetVerticesIndexFront(){ int index = front.verticesIndex; return index;
} public double GetDistanceFront(){ double dis = front.distance; return dis;
{ throw new InvalidOperationException("Queue is empty.");
● Lớp Province lưu thông tin các địa điểm:
2 public double x { get; private set; }
3 public double y { get; private set; }
9 public string provinceName { get; private set; }
10 public string verticesName { get; private set; }
11 public VerticesXY verticesLocation { get; private set; }
12 public Province(string provinceName, string verticesName, double x, double y){
● Lớp Vertex lưu thông tin các đỉnh:
2 public string nameVertices { get; private set; }
3 public bool wasVisited { get; set; }
4 public string previousVertices { get; set; }
5 public double pathLenght { get; set; }
The Graph class is designed to handle a maximum of 100 vertices, with a constant value representing infinity set to 99999 It initializes variables to track the number of vertices, an adjacency matrix, and a list of adjacent vertices for each vertex The constructor creates an array for storing vertex objects and initializes an adjacency list for each vertex, ensuring efficient representation and management of graph data.
} adjacency = new int[MaxCountVertices, MaxCountVertices];
} public void AddVertices(string s){ vertices[countOfVertices++] = new Vertex(s);
61 public void InsertEdge(string v1, string v2, int v3){ int i = GetIndex(v1); int j = GetIndex(v2); adjacency[i, j] = v3; adjacency[j, i] = v3; adjacencyVertices[i].Add(j); adjacencyVertices[j].Add(i);
} public int GetIndex(string s){ for int ( i = 0; i < countOfVertices; i++{
} throw new System.InvalidOperationException("Invalid Vertex");
} public void Dijkstra(string s){ for int ( i = 0; i < countOfVertices; i++)
(vertices[i].nameVertices == s) if vertices[i].pathLenght = 0; else vertices[i].pathLenght = INF; vertices[i].previousVertices = ; ""
PriorityQueueForGraph(); distance_name.Enqueue(0, GetIndex(s)); while (!distance_name.IsEmpty()){ double kc = distance_name.GetDistanceFront(); int vertices = distance_name.GetVerticesIndexFront(); distance_name.Dequeue();
(if this.vertices[vertices].wasVisited){ continue;
} this.vertices[vertices].wasVisited = true; foreach int ( y adjacencyVertices[vertices]){ in double w = adjacency[y, vertices];
(this.vertices[vertices].pathLenght + w)){ this.vertices[y].pathLenght this.vertices[vertices].pathLenght + w; distance_name.Enqueue(this.vertices[y].pathLenght, y);
93 this.vertices[y].previousVertices this.vertices[vertices].nameVertices;
}}}} public void PathInformation(string start, string end, TextBox Path,
TextBox pathLength, TextBox fuel, TextBox cost){
List paths = new List(); double km = vertices[GetIndex(end)].pathLenght; pathLength.Text = $"{km} km"; fuel.Text = {km / 100 * 9}$" liters"; cost.Text = {km / 100 * 9 * 22.7}$" VND";
Console.WriteLine(km); while true ( ){ paths.Add(end);
} end = vertices[GetIndex(end)].previousVertices;
Console.WriteLine(); foreach string ( k paths) { in
3.1 Giao Di ện Menu Chính
3.1.1 Giớ i thi u chung giao di ệ ện:
3.1.2 Hướng dẫn sử dụng giao diện:
- Chọn điểm đầu (điểm đi) và điểm cuối (điểm đến)::
- Không ch ọn điểm đầ u và cu i trùng nhau: ố
3.2.1 B ản đồ khu v c m t s t nh mi n B c Vi t Nam ự ộ ố ỉ ề ắ ệ
Bản đồ hiển thị thông tin được đo đạc và cung cấp cho người dùng các dữ liệu quan trọng như địa điểm vận chuyển, các tuyến đường, và độ dài của từng tuyến đường.
Mã ngu n các hàm ch ồ ức năng:
Hàm thêm các điểm và các t nh vào tỉ ọa độ theo bản đồ
1 public List Provinces = new List();
3 private void Form1_Load(object sender, EventArgs e){
4 Province haGiang = new Province("Hà Giang" "A", , 85, 140);
5 Province caoBang = new Province("Cao Bằng" "B", , 225, 140);
6 Province tuyenQuang = new Province("Tuyên Quang" "C", , 125,
7 Province phuTho = new Province("Phú Thọ" "D", , 113, 325);
8 Province haNoi = new Province("Hà Nội" "E", , 192, 370);
9 Province namDinh = new Province("Nam Định" "F", , 245, 455);
10 Province haiPhong = new Province("Hải Phòng" "G", , 290, 395);
11 Province quangNinh = new Province("Quảng Ninh" "H", , 359, 351);
12 Province langSon = new Province("Lạng Sơn", "I", 283, 260);
13 Province banKan = new Province("Bắc Kạn", "K", 194, 205);
14 Province bacGiang = new Province("Bắc Giang" "L", , 275, 321);
Hàm vẽ các điểm và nối các điểm thành các tuyến đường
1 private void southMap_Paint(object creator, PaintEventArgs e){
5 DrawLine("Hà Giang", "Cao Bằng");
6 DrawLine("Cao Bằng", "Lạng Sơn");
7 DrawLine("Lạng Sơn", "Bắc Giang");
8 DrawLine("Bắc Giang", "Quảng Ninh");
9 DrawLine("Quảng Ninh", "Hải Phòng");
10 DrawLine("Hải Phòng", "Nam Định");
11 DrawLine("Nam Định", "Hà Nội");
12 DrawLine("Hà Nội", "Hải Phòng");
13 DrawLine("Bắc Giang", "Hà Nội");
14 DrawLine("Hà Nội", "Bắc Kạn");
15 DrawLine("Hà Nội", "Phú Thọ");
16 DrawLine("Phú Thọ", "Tuyên Quang");
17 DrawLine("Tuyên Quang", "Hà Giang");
18 DrawLine("Bắc Kạn", "Hà Giang");
19 DrawLine("Bắc Kạn", "Tuyên Quang");
20 DrawLine("Bắc Kạn", "Cao Bằng");
21 DrawLine("Bắc Kạn", "Phú Thọ");
22 DrawLine("Bắc Kạn", "Lạng Sơn");
24 private void DrawLine(string a, string b){
28 Pen p = new Pen(Color.Black, 2);
29 Point point1 = new Point(g.listPoints[x].X, g.listPoints[x].Y);
30 Point point2 = new Point(g.listPoints[y].X, g.listPoints[y].Y);
32 graph.DrawString($"{g.adjacency[x, y]}", new Font("Fira Code",
33 10), Brushes.Black, new Point((point1.X + point2.X) / 2 - 22,
Hàm thể hiệ độn dài các tuyến đường
5 g.InsertEdge("Hà Giang", "Cao Bằng", 136);
6 g.InsertEdge("Cao Bằng", "Lạng Sơn", 95);
7 g.InsertEdge("Lạng Sơn", "Bắc Giang", 62);
8 g.InsertEdge("Bắc Giang", "Quảng Ninh", 76);
9 g.InsertEdge("Quảng Ninh", "Hải Phòng", 77);
10 g.InsertEdge("Hải Phòng", "Nam Định", 77);
11 g.InsertEdge("Nam Định", "Hà Nội", 90);
12 g.InsertEdge("Hà Nội", "Hải Phòng", 82);
13 g.InsertEdge("Bắc Giang", "Hà Nội", 90);
14 g.InsertEdge("Hà Nội", "Bắc Kạn", 70);
15 g.InsertEdge("Hà Nội", "Phú Thọ", 136);
16 g.InsertEdge("Phú Thọ", "Tuyên Quang", 101);
17 g.InsertEdge("Tuyên Quang", "Hà Giang", 76);
18 g.InsertEdge("Bắc Kạn", "Hà Giang", 109);
19 g.InsertEdge("Bắc Kạn", "Tuyên Quang", 60);
20 g.InsertEdge("Bắc Kạn", "Cao Bằng", 53);
21 g.InsertEdge("Bắc Kạn", "Phú Thọ", 134);
22 g.InsertEdge("Bắc Kạn", "Lạng Sơn", 92);
Hàm v tuyẽ ết đường ti t ki m nhế ệ ất tính toán được lên bản đồ
3 Pen p = new Pen(Color.Red, 3);
4 Point point1 = new Point(g.pathIndex[i].X, g.pathIndex[i].Y);
5 Point point2 = new Point(g.pathIndex[i + 1].X, g.pathIndex[i
3.2.2 Khung nh p và hi n th k t qu ậ ệ ị ế ả
- Khung nh p thông tin g ậ ồm điểm đi và điểm đến
Cài Đặt Lớp
● Lớp NodePriorityQueue và PriorityQueueForGraph hỗ trợ cho thuật toán Dijkstra
The NodePriorityQueue class represents a node in a priority queue, featuring properties for distance and vertex index It includes a constructor that initializes these properties, and a reference to the next node in the queue This structure is essential for implementing efficient algorithms in graph theory, allowing for the management of nodes based on their distance values.
}} public classPriorityQueueForGraph{ private NodePriorityQueue front; publicPriorityQueueForGraph(){ front = null;
} public void Enqueue(double distance, int verticesIndex) {
NodePriorityQueue newNode = new NodePriorityQueue(distance, verticesIndex);
// Nếu hàng đợi tr ng ho c ố ặ đỉnh có độ ư u ti n cao h n nh ê ơ đỉ đầu tiên
(front == if null || distance < front.distance){
57 newNode.next = front; front = newNode;
// Tìm nh có đỉ độ u tiư ên cao h n ơ đểchèn sau đó while (current.next != null && distance > current.next.distance){ current = current.next;
} newNode.next = current.next; current.next = newNode;
(front == if null){ return true;
} public int GetVerticesIndexFront(){ int index = front.verticesIndex; return index;
} public double GetDistanceFront(){ double dis = front.distance; return dis;
{ throw new InvalidOperationException("Queue is empty.");
● Lớp Province lưu thông tin các địa điểm:
2 public double x { get; private set; }
3 public double y { get; private set; }
9 public string provinceName { get; private set; }
10 public string verticesName { get; private set; }
11 public VerticesXY verticesLocation { get; private set; }
12 public Province(string provinceName, string verticesName, double x, double y){
● Lớp Vertex lưu thông tin các đỉnh:
2 public string nameVertices { get; private set; }
3 public bool wasVisited { get; set; }
4 public string previousVertices { get; set; }
5 public double pathLenght { get; set; }
The Graph class is designed to manage a graph structure with a maximum of 100 vertices, utilizing a two-dimensional array for adjacency representation and a list for adjacency vertices It initializes the count of vertices to zero and creates an array of Vertex objects along with a list of adjacency lists for each vertex Each adjacency list is instantiated within a loop, ensuring that all vertices are prepared for graph operations.
} adjacency = new int[MaxCountVertices, MaxCountVertices];
} public void AddVertices(string s){ vertices[countOfVertices++] = new Vertex(s);
61 public void InsertEdge(string v1, string v2, int v3){ int i = GetIndex(v1); int j = GetIndex(v2); adjacency[i, j] = v3; adjacency[j, i] = v3; adjacencyVertices[i].Add(j); adjacencyVertices[j].Add(i);
} public int GetIndex(string s){ for int ( i = 0; i < countOfVertices; i++{
} throw new System.InvalidOperationException("Invalid Vertex");
} public void Dijkstra(string s){ for int ( i = 0; i < countOfVertices; i++)
(vertices[i].nameVertices == s) if vertices[i].pathLenght = 0; else vertices[i].pathLenght = INF; vertices[i].previousVertices = ; ""
PriorityQueueForGraph(); distance_name.Enqueue(0, GetIndex(s)); while (!distance_name.IsEmpty()){ double kc = distance_name.GetDistanceFront(); int vertices = distance_name.GetVerticesIndexFront(); distance_name.Dequeue();
(if this.vertices[vertices].wasVisited){ continue;
} this.vertices[vertices].wasVisited = true; foreach int ( y adjacencyVertices[vertices]){ in double w = adjacency[y, vertices];
(this.vertices[vertices].pathLenght + w)){ this.vertices[y].pathLenght this.vertices[vertices].pathLenght + w; distance_name.Enqueue(this.vertices[y].pathLenght, y);
93 this.vertices[y].previousVertices this.vertices[vertices].nameVertices;
}}}} public void PathInformation(string start, string end, TextBox Path,
TextBox pathLength, TextBox fuel, TextBox cost){
List paths = new List(); double km = vertices[GetIndex(end)].pathLenght; pathLength.Text = $"{km} km"; fuel.Text = {km / 100 * 9}$" liters"; cost.Text = {km / 100 * 9 * 22.7}$" VND";
Console.WriteLine(km); while true ( ){ paths.Add(end);
} end = vertices[GetIndex(end)].previousVertices;
Console.WriteLine(); foreach string ( k paths) { in
3.1 Giao Di ện Menu Chính
3.1.1 Giớ i thi u chung giao di ệ ện:
3.1.2 Hướng dẫn sử dụng giao diện:
- Chọn điểm đầu (điểm đi) và điểm cuối (điểm đến)::
- Không ch ọn điểm đầ u và cu i trùng nhau: ố
3.2.1 B ản đồ khu v c m t s t nh mi n B c Vi t Nam ự ộ ố ỉ ề ắ ệ
Bản đồ hiển thị thông tin chi tiết về các địa điểm vận chuyển, các tuyến đường và độ dài của từng tuyến đường, giúp người dùng dễ dàng nắm bắt và sử dụng.
Mã ngu n các hàm ch ồ ức năng:
Hàm thêm các điểm và các t nh vào tỉ ọa độ theo bản đồ
1 public List Provinces = new List();
3 private void Form1_Load(object sender, EventArgs e){
4 Province haGiang = new Province("Hà Giang" "A", , 85, 140);
5 Province caoBang = new Province("Cao Bằng" "B", , 225, 140);
6 Province tuyenQuang = new Province("Tuyên Quang" "C", , 125,
7 Province phuTho = new Province("Phú Thọ" "D", , 113, 325);
8 Province haNoi = new Province("Hà Nội" "E", , 192, 370);
9 Province namDinh = new Province("Nam Định" "F", , 245, 455);
10 Province haiPhong = new Province("Hải Phòng" "G", , 290, 395);
11 Province quangNinh = new Province("Quảng Ninh" "H", , 359, 351);
12 Province langSon = new Province("Lạng Sơn", "I", 283, 260);
13 Province banKan = new Province("Bắc Kạn", "K", 194, 205);
14 Province bacGiang = new Province("Bắc Giang" "L", , 275, 321);
Hàm vẽ các điểm và nối các điểm thành các tuyến đường
1 private void southMap_Paint(object creator, PaintEventArgs e){
5 DrawLine("Hà Giang", "Cao Bằng");
6 DrawLine("Cao Bằng", "Lạng Sơn");
7 DrawLine("Lạng Sơn", "Bắc Giang");
8 DrawLine("Bắc Giang", "Quảng Ninh");
9 DrawLine("Quảng Ninh", "Hải Phòng");
10 DrawLine("Hải Phòng", "Nam Định");
11 DrawLine("Nam Định", "Hà Nội");
12 DrawLine("Hà Nội", "Hải Phòng");
13 DrawLine("Bắc Giang", "Hà Nội");
14 DrawLine("Hà Nội", "Bắc Kạn");
15 DrawLine("Hà Nội", "Phú Thọ");
16 DrawLine("Phú Thọ", "Tuyên Quang");
17 DrawLine("Tuyên Quang", "Hà Giang");
18 DrawLine("Bắc Kạn", "Hà Giang");
19 DrawLine("Bắc Kạn", "Tuyên Quang");
20 DrawLine("Bắc Kạn", "Cao Bằng");
21 DrawLine("Bắc Kạn", "Phú Thọ");
22 DrawLine("Bắc Kạn", "Lạng Sơn");
24 private void DrawLine(string a, string b){
28 Pen p = new Pen(Color.Black, 2);
29 Point point1 = new Point(g.listPoints[x].X, g.listPoints[x].Y);
30 Point point2 = new Point(g.listPoints[y].X, g.listPoints[y].Y);
32 graph.DrawString($"{g.adjacency[x, y]}", new Font("Fira Code",
33 10), Brushes.Black, new Point((point1.X + point2.X) / 2 - 22,
Hàm thể hiệ độn dài các tuyến đường
5 g.InsertEdge("Hà Giang", "Cao Bằng", 136);
6 g.InsertEdge("Cao Bằng", "Lạng Sơn", 95);
7 g.InsertEdge("Lạng Sơn", "Bắc Giang", 62);
8 g.InsertEdge("Bắc Giang", "Quảng Ninh", 76);
9 g.InsertEdge("Quảng Ninh", "Hải Phòng", 77);
10 g.InsertEdge("Hải Phòng", "Nam Định", 77);
11 g.InsertEdge("Nam Định", "Hà Nội", 90);
12 g.InsertEdge("Hà Nội", "Hải Phòng", 82);
13 g.InsertEdge("Bắc Giang", "Hà Nội", 90);
14 g.InsertEdge("Hà Nội", "Bắc Kạn", 70);
15 g.InsertEdge("Hà Nội", "Phú Thọ", 136);
16 g.InsertEdge("Phú Thọ", "Tuyên Quang", 101);
17 g.InsertEdge("Tuyên Quang", "Hà Giang", 76);
18 g.InsertEdge("Bắc Kạn", "Hà Giang", 109);
19 g.InsertEdge("Bắc Kạn", "Tuyên Quang", 60);
20 g.InsertEdge("Bắc Kạn", "Cao Bằng", 53);
21 g.InsertEdge("Bắc Kạn", "Phú Thọ", 134);
22 g.InsertEdge("Bắc Kạn", "Lạng Sơn", 92);
Hàm v tuyẽ ết đường ti t ki m nhế ệ ất tính toán được lên bản đồ
3 Pen p = new Pen(Color.Red, 3);
4 Point point1 = new Point(g.pathIndex[i].X, g.pathIndex[i].Y);
5 Point point2 = new Point(g.pathIndex[i + 1].X, g.pathIndex[i
3.2.2 Khung nh p và hi n th k t qu ậ ệ ị ế ả
- Khung nh p thông tin g ậ ồm điểm đi và điểm đến
Khung hiển thị kết quả giao nhiên liệu để tính toán khoảng cách, chi phí và thời gian vận chuyển, giúp xác định đường đi ngắn nhất Nhiên liệu được tính toán dựa trên khoảng cách, ví dụ, khi di chuyển 100 km sẽ cần khoảng 9 lít xăng.
Mã ngu n các hàm ch ồ ức năng:
Hàm để thêm các thông tin vào input
1 //thêm phần t ửvào box điểm i đ
2 cbSource.Items.Add("Hà Giang");
3 cbSource.Items.Add("Cao Bằng");
4 cbSource.Items.Add("Tuyên Quang");
5 cbSource.Items.Add("Phú Thọ");
6 cbSource.Items.Add("Hà Nội");
7 cbSource.Items.Add("Nam Định");
8 cbSource.Items.Add("Hải Phòng");
9 cbSource.Items.Add("Quảng Ninh");
10 cbSource.Items.Add("Lạng Sơn");
11 cbSource.Items.Add("Bắc Kạn");
12 cbSource.Items.Add("Bắc Giang");
13 //thêm phần t ửvào box điểm đến
14 cbDestination.Items.Add("Hà Giang");
15 cbDestination.Items.Add("Cao Bằng");
16 cbDestination.Items.Add("Tuyên Quang");
17 cbDestination.Items.Add("Phú Thọ");
18 cbDestination.Items.Add("Hà Nội");
19 cbDestination.Items.Add("Nam Định");
20 cbDestination.Items.Add("Hải Phòng");
21 cbDestination.Items.Add("Quảng Ninh");
22 cbDestination.Items.Add("Lạng Sơn");
23 cbDestination.Items.Add("Bắc Kạn");
24 cbDestination.Items.Add("Bắc Giang");
Hàm xóa các thông tin đã in ra từ trước khi nhập input khác và thông báo l i khi nh ỗ ập trùng điể m đi và điểm đế n
1 private void cbSource_SelectedIndexChanged(object
3 if (cbSource.SelectedIndex!=-1 &&cbDestination.SelectedIndex!=1){
12 g.findPaths(cbSource.SelectedItem.ToString(),cbDestination
13 SelectedIndex.ToString(), tbKM, tbLiter, tbCost, tbPath);
18 if (cbSource.SelectedIndex == cbDestination.SelectedIndex){
19 MessageBox.Show(" iĐ ểm i trđ ùng v i ớ đ ểm đến Vui lòng nhập i
23 private void cbDestination_SelectedIndexChanged(object creator,
25 if(cbSource.SelectedIndex!=-1 && cbDestination.SelectedIndex!=-1){
34 g.findPaths(cbSource.SelectedItem.ToString(),cbDestination
35 SelectedIndex.ToString(), tbKM, tbLiter, tbCost, tbPath);
38 if (cbSource.SelectedIndex == cbDestination.SelectedIndex)
40 MessageBox.Show(" iĐ ểm i trđ ùng v i ớ điểm đến Vui lòng nh p lậ ại.”);
CHƯƠNG 4 THẢO LU ẬN & ĐÁNH GIÁ
- Đường đi ngắ n nh t t ấ ừ “Hà Giang” đến “Cao Bằng” và chi phí
- Đường đi ngắ n nh t t ấ ừ “Hà Nộ ” đến “ i Tuyên Quang ” và chi phí.
Thuật toán Dijkstra là một công cụ mạnh mẽ giúp tìm ra đường đi ngắn nhất một cách hiệu quả Không chỉ giới hạn trong việc xác định lộ trình, thuật toán này còn được áp dụng rộng rãi trong tối ưu hóa chi phí, đo khoảng cách và tính toán nhiên liệu tiêu thụ, từ đó trở thành lựa chọn hàng đầu cho nhiều doanh nghiệp.
Winform là một yếu tố quan trọng giúp tạo ra giao diện đẹp mắt và dễ sử dụng cho người dùng Với yêu cầu kỹ thuật không quá cao, Winform đã trở thành lựa chọn phổ biến không chỉ cho các doanh nghiệp mà còn cho những người mới bắt đầu học lập trình và thiết kế giao diện.
Ứng dụng tối ưu tuyến đường không chỉ giúp xử lý các chuyến đi đến nhiều địa điểm mà còn cho phép người dùng thao tác dễ dàng từ địa điểm này đến địa điểm khác Bằng cách sử dụng dữ liệu tọa độ, ứng dụng tìm ra tuyến đường ngắn nhất, từ đó tiết kiệm nhiên liệu và giảm hao mòn cho xe Thông qua đồ thị, sự liên kết giữa các địa điểm trở nên rõ ràng và trực quan hơn.
Trong cuộc sống bận rộn hiện nay, việc tìm đường đi bằng phương pháp thủ công tốn nhiều thời gian Đồ án “ỨNG DỤNG THUẬT TOÁN DIJKSTRA TỐI ƯU HÓA CHI PHÍ VẬN TẢI” sẽ giúp bạn giải quyết vấn đề này một cách hiệu quả Ứng dụng này không chỉ giúp tiết kiệm chi phí vận chuyển mà còn tối ưu hóa chi phí cho doanh nghiệp, mang lại hiệu quả cao hơn bao giờ hết.
Hạn chế lớn nhất khi áp dụng đồ án vào thực tế là khoảng cách giữa các địa điểm được thể hiện dưới dạng đoạn thẳng Điều này không phản ánh đúng thực tế, vì đường đi thường có nhiều khúc cua và đèo dốc, ảnh hưởng đến lộ trình di chuyển Do đó, tính ứng dụng của đồ án chưa cao.
- Chưa có bản giá vận chuyển cụ thể cho từng Tỉnh đi đến
Người dùng có thể gặp khó khăn trong việc xác định điểm đi và điểm đến do mô hình không cung cấp đầy đủ các địa điểm cần thiết, dẫn đến sự khó chịu và có thể khiến họ ngừng sử dụng dịch vụ Điều này không chỉ ảnh hưởng đến trải nghiệm người dùng mà còn gây bất lợi cho doanh nghiệp, khi một số người tìm kiếm lộ trình khác có chứa địa điểm họ cần Do đó, việc cải thiện mô hình để đáp ứng nhu cầu của người dùng là rất quan trọng để giữ chân khách hàng và tăng cường sự hài lòng.
- Chưa cập nhật các yếu tố thời gian thực như tắc nghẽn giao thông, ảnh hưởng của thời tiết, điều kiện đường đi, giá xăng dầu
Giao diện đồ án cần phải trở nên cuốn hút hơn để thu hút người dùng, đặc biệt trong bối cảnh công nghệ ngày càng phát triển với nhiều mô hình hấp dẫn Khách hàng hiện đại, đặc biệt là những người khó tính và tinh tế, thường ưu tiên lựa chọn ứng dụng có thiết kế bắt mắt và chức năng đa dạng để đáp ứng nhu cầu của họ Nếu mô hình không thu hút được sự chú ý của khách hàng, khả năng họ quay lại sử dụng sẽ rất thấp.
Đề xuất 1: Để cải thiện tính trực quan của mô hình, nên xây dựng đồ án dựa trên đường đi thực tế thay vì sử dụng đường thẳng Việc này sẽ giúp mô hình trở nên trực quan và tối ưu hơn Đường thẳng thường phù hợp hơn với giao thông đường hàng không hoặc đường biển.
- Đề xuất 2: Thêm thông tin ảnh hưởng chi phí vận tải trên bản đồ:
• Cập nhật thời tiết theo thời gian
• Cập nhật giá xăng dầu qua từng ngày
• Cập nhật màu sắc đường đi trên đoạn đường ùn tắc
• Cập nhật số lượng trạm thu phí trên suốt đường đi
• Cập nhật bản giá vận chuyển cụ thể cho từng Tỉnh
Mô hình đề xuất có khả năng tích hợp nhiều yếu tố, cho phép người dùng truy cập vào một ứng dụng duy nhất để nhận thông tin đa dạng về giao thông Ứng dụng sẽ cung cấp thời gian di chuyển giữa các điểm, mật độ giao thông hiện tại, và đề xuất tuyến đường thay thế khi tuyến đường ngắn nhất gặp tình trạng ùn tắc hoặc tai nạn, giúp người dùng kịp thời điều chỉnh lộ trình của mình.
Việc mở rộng mô hình địa điểm là cần thiết để tăng cường sự đa dạng, không chỉ giới hạn ở miền Đông Bắc Việt Nam Chúng ta có thể cung cấp cho người dùng nhiều lựa chọn hơn từ khắp các khu vực và tỉnh thành trong cả nước, giúp họ thoải mái chọn lựa giữa nhiều điểm đến trong mỗi tỉnh thành.
Toàn b mã ngu n có th ộ ồ ể được tìm th y t i ấ ạ Link Github
Viết Hướ ng D ẫn Cách Cài Đặt Để Chạy
Bước 1: Truy c ập vào đườ ng Link Github để xem dự án nhóm đã tải lên
Bước 2: T ải chương trình bằ ng cách làm theo hình sau:
Sau khi n vào Download ZIP, vào ph n Download c a trình duy ấ ầ ủ ệt để kiểm tra
Sau khi tải xong tệp, bạn cần truy cập vào thư mục lưu trữ Có thể nhấp vào "Hiển thị" trong trình duyệt để đến nơi lưu tệp Tại đây, hãy nhấn chuột phải vào thư mục và chọn "Extract files" để tiến hành giải nén.
Sau kh i ấ n vào Extract files s hi n lên c a s ẽ ệ ử ổ như sau:
THIẾT KẾ GIAO DIỆN
Chi Ti t Ch ế ức Năng
- Không ch ọn điểm đầ u và cu i trùng nhau: ố
3.2.1 B ản đồ khu v c m t s t nh mi n B c Vi t Nam ự ộ ố ỉ ề ắ ệ
Bản đồ hiển thị thông tin được đo đạc và liệt kê cho người dùng, bao gồm các địa điểm vận chuyển, các tuyến đường và độ dài của từng tuyến đường.
Mã ngu n các hàm ch ồ ức năng:
Hàm thêm các điểm và các t nh vào tỉ ọa độ theo bản đồ
1 public List Provinces = new List();
3 private void Form1_Load(object sender, EventArgs e){
4 Province haGiang = new Province("Hà Giang" "A", , 85, 140);
5 Province caoBang = new Province("Cao Bằng" "B", , 225, 140);
6 Province tuyenQuang = new Province("Tuyên Quang" "C", , 125,
7 Province phuTho = new Province("Phú Thọ" "D", , 113, 325);
8 Province haNoi = new Province("Hà Nội" "E", , 192, 370);
9 Province namDinh = new Province("Nam Định" "F", , 245, 455);
10 Province haiPhong = new Province("Hải Phòng" "G", , 290, 395);
11 Province quangNinh = new Province("Quảng Ninh" "H", , 359, 351);
12 Province langSon = new Province("Lạng Sơn", "I", 283, 260);
13 Province banKan = new Province("Bắc Kạn", "K", 194, 205);
14 Province bacGiang = new Province("Bắc Giang" "L", , 275, 321);
Hàm vẽ các điểm và nối các điểm thành các tuyến đường
1 private void southMap_Paint(object creator, PaintEventArgs e){
5 DrawLine("Hà Giang", "Cao Bằng");
6 DrawLine("Cao Bằng", "Lạng Sơn");
7 DrawLine("Lạng Sơn", "Bắc Giang");
8 DrawLine("Bắc Giang", "Quảng Ninh");
9 DrawLine("Quảng Ninh", "Hải Phòng");
10 DrawLine("Hải Phòng", "Nam Định");
11 DrawLine("Nam Định", "Hà Nội");
12 DrawLine("Hà Nội", "Hải Phòng");
13 DrawLine("Bắc Giang", "Hà Nội");
14 DrawLine("Hà Nội", "Bắc Kạn");
15 DrawLine("Hà Nội", "Phú Thọ");
16 DrawLine("Phú Thọ", "Tuyên Quang");
17 DrawLine("Tuyên Quang", "Hà Giang");
18 DrawLine("Bắc Kạn", "Hà Giang");
19 DrawLine("Bắc Kạn", "Tuyên Quang");
20 DrawLine("Bắc Kạn", "Cao Bằng");
21 DrawLine("Bắc Kạn", "Phú Thọ");
22 DrawLine("Bắc Kạn", "Lạng Sơn");
24 private void DrawLine(string a, string b){
28 Pen p = new Pen(Color.Black, 2);
29 Point point1 = new Point(g.listPoints[x].X, g.listPoints[x].Y);
30 Point point2 = new Point(g.listPoints[y].X, g.listPoints[y].Y);
32 graph.DrawString($"{g.adjacency[x, y]}", new Font("Fira Code",
33 10), Brushes.Black, new Point((point1.X + point2.X) / 2 - 22,
Hàm thể hiệ độn dài các tuyến đường
5 g.InsertEdge("Hà Giang", "Cao Bằng", 136);
6 g.InsertEdge("Cao Bằng", "Lạng Sơn", 95);
7 g.InsertEdge("Lạng Sơn", "Bắc Giang", 62);
8 g.InsertEdge("Bắc Giang", "Quảng Ninh", 76);
9 g.InsertEdge("Quảng Ninh", "Hải Phòng", 77);
10 g.InsertEdge("Hải Phòng", "Nam Định", 77);
11 g.InsertEdge("Nam Định", "Hà Nội", 90);
12 g.InsertEdge("Hà Nội", "Hải Phòng", 82);
13 g.InsertEdge("Bắc Giang", "Hà Nội", 90);
14 g.InsertEdge("Hà Nội", "Bắc Kạn", 70);
15 g.InsertEdge("Hà Nội", "Phú Thọ", 136);
16 g.InsertEdge("Phú Thọ", "Tuyên Quang", 101);
17 g.InsertEdge("Tuyên Quang", "Hà Giang", 76);
18 g.InsertEdge("Bắc Kạn", "Hà Giang", 109);
19 g.InsertEdge("Bắc Kạn", "Tuyên Quang", 60);
20 g.InsertEdge("Bắc Kạn", "Cao Bằng", 53);
21 g.InsertEdge("Bắc Kạn", "Phú Thọ", 134);
22 g.InsertEdge("Bắc Kạn", "Lạng Sơn", 92);
Hàm v tuyẽ ết đường ti t ki m nhế ệ ất tính toán được lên bản đồ
3 Pen p = new Pen(Color.Red, 3);
4 Point point1 = new Point(g.pathIndex[i].X, g.pathIndex[i].Y);
5 Point point2 = new Point(g.pathIndex[i + 1].X, g.pathIndex[i
3.2.2 Khung nh p và hi n th k t qu ậ ệ ị ế ả
- Khung nh p thông tin g ậ ồm điểm đi và điểm đến
Khung hiển thị kết quả giao thông tự động giúp người dùng tiết kiệm thời gian, khoảng cách và chi phí vận chuyển Nhiên liệu được tính toán dựa trên khoảng cách di chuyển, ví dụ như khi đi 100km sẽ cần khoảng 9 lít xăng.
Mã ngu n các hàm ch ồ ức năng:
Hàm để thêm các thông tin vào input
1 //thêm phần t ửvào box điểm i đ
2 cbSource.Items.Add("Hà Giang");
3 cbSource.Items.Add("Cao Bằng");
4 cbSource.Items.Add("Tuyên Quang");
5 cbSource.Items.Add("Phú Thọ");
6 cbSource.Items.Add("Hà Nội");
7 cbSource.Items.Add("Nam Định");
8 cbSource.Items.Add("Hải Phòng");
9 cbSource.Items.Add("Quảng Ninh");
10 cbSource.Items.Add("Lạng Sơn");
11 cbSource.Items.Add("Bắc Kạn");
12 cbSource.Items.Add("Bắc Giang");
13 //thêm phần t ửvào box điểm đến
14 cbDestination.Items.Add("Hà Giang");
15 cbDestination.Items.Add("Cao Bằng");
16 cbDestination.Items.Add("Tuyên Quang");
17 cbDestination.Items.Add("Phú Thọ");
18 cbDestination.Items.Add("Hà Nội");
19 cbDestination.Items.Add("Nam Định");
20 cbDestination.Items.Add("Hải Phòng");
21 cbDestination.Items.Add("Quảng Ninh");
22 cbDestination.Items.Add("Lạng Sơn");
23 cbDestination.Items.Add("Bắc Kạn");
24 cbDestination.Items.Add("Bắc Giang");
Hàm xóa các thông tin đã in ra từ trước khi nhập input khác và thông báo l i khi nh ỗ ập trùng điể m đi và điểm đế n
1 private void cbSource_SelectedIndexChanged(object
3 if (cbSource.SelectedIndex!=-1 &&cbDestination.SelectedIndex!=1){
12 g.findPaths(cbSource.SelectedItem.ToString(),cbDestination
13 SelectedIndex.ToString(), tbKM, tbLiter, tbCost, tbPath);
18 if (cbSource.SelectedIndex == cbDestination.SelectedIndex){
19 MessageBox.Show(" iĐ ểm i trđ ùng v i ớ đ ểm đến Vui lòng nhập i
23 private void cbDestination_SelectedIndexChanged(object creator,
25 if(cbSource.SelectedIndex!=-1 && cbDestination.SelectedIndex!=-1){
34 g.findPaths(cbSource.SelectedItem.ToString(),cbDestination
35 SelectedIndex.ToString(), tbKM, tbLiter, tbCost, tbPath);
38 if (cbSource.SelectedIndex == cbDestination.SelectedIndex)
40 MessageBox.Show(" iĐ ểm i trđ ùng v i ớ điểm đến Vui lòng nh p lậ ại.”);
THẢ O LU ẬN & ĐÁNH GIÁ
Các K t Qu ế ả Nhận Được
- Đường đi ngắ n nh t t ấ ừ “Hà Giang” đến “Cao Bằng” và chi phí
- Đường đi ngắ n nh t t ấ ừ “Hà Nộ ” đến “ i Tuyên Quang ” và chi phí.
Thuật toán Dijkstra là một công cụ mạnh mẽ để tìm đường đi ngắn nhất, không chỉ trong việc xác định lộ trình mà còn trong tối ưu hóa chi phí, đo khoảng cách và tiêu thụ nhiên liệu Nhờ vào tính hiệu quả và linh hoạt của nó, thuật toán này đã trở thành sự lựa chọn hàng đầu cho nhiều doanh nghiệp trong việc giải quyết các bài toán phức tạp liên quan đến lộ trình và chi phí.
Winform là một yếu tố quan trọng giúp tạo ra giao diện đẹp mắt và dễ sử dụng cho người dùng Với yêu cầu kỹ thuật không quá cao, Winform được nhiều người biết đến và ưa chuộng, không chỉ trong các doanh nghiệp mà còn đối với những người mới bắt đầu học lập trình và thiết kế giao diện.
Ứng dụng tối ưu tuyến đường không chỉ giúp tìm ra lộ trình ngắn nhất cho các chuyến đi đến nhiều địa điểm mà còn sử dụng dữ liệu tọa độ để tiết kiệm nhiên liệu và giảm hao mòn xe Nhờ vào đồ thị, người dùng có thể dễ dàng nhận thấy sự liên kết giữa các địa điểm một cách rõ ràng và trực quan.
Trong cuộc sống bận rộn hiện nay, việc tìm đường đi bằng phương pháp thủ công tốn nhiều thời gian Đồ án "ỨNG DỤNG THUẬT TOÁN DIJKSTRA TỐI ƯU HÓA CHI PHÍ VẬN TẢI" sẽ giúp bạn giải quyết vấn đề này một cách hiệu quả Ứng dụng này không chỉ tiết kiệm chi phí phát sinh trong quá trình vận chuyển mà còn tối ưu hóa chi phí cho doanh nghiệp, nâng cao hiệu quả hoạt động hơn bao giờ hết.
Hạn chế lớn nhất khi áp dụng đồ án vào thực tế là việc các địa điểm được kết nối bằng đoạn thẳng, trong khi đường đi thực tế thường không thẳng mà có thể có những khúc cua hoặc đèo dốc Điều này ảnh hưởng đến lộ trình di chuyển và làm giảm tính ứng dụng của đồ án.
- Chưa có bản giá vận chuyển cụ thể cho từng Tỉnh đi đến
Người dùng có thể gặp khó khăn trong việc xác định điểm đi và điểm đến do mô hình không cung cấp đầy đủ địa điểm cần thiết, gây ra sự khó chịu và có thể dẫn đến việc họ ngừng sử dụng dịch vụ Nếu gặp tình trạng này, nhiều người sẽ chuyển sang mô hình khác, điều mà doanh nghiệp không mong muốn Một số ít người sẽ tìm kiếm lộ trình khác có chứa địa điểm họ cần, nhưng điều này cũng gây ra bất lợi cho doanh nghiệp.
- Chưa cập nhật các yếu tố thời gian thực như tắc nghẽn giao thông, ảnh hưởng của thời tiết, điều kiện đường đi, giá xăng dầu
Giao diện đồ án cần được cải thiện để thu hút người dùng hơn, đặc biệt trong bối cảnh công nghệ ngày càng phát triển với nhiều mô hình bắt mắt Khách hàng khó tính và tinh tế thường ưu tiên các ứng dụng không chỉ đẹp mắt mà còn có chức năng đa dạng để đáp ứng nhu cầu của họ Nếu mô hình không thu hút được sự chú ý của khách hàng, khả năng họ quay lại sử dụng sẽ rất thấp.
Đề xuất 1: Mô hình cần được cải thiện về tính trực quan bằng cách xây dựng đồ án dựa trên đường đi thực tế, thay vì sử dụng đường thẳng Việc này sẽ giúp mô hình trở nên trực quan và tối ưu hơn, đặc biệt phù hợp với giao thông đường hàng không hoặc đường biển.
- Đề xuất 2: Thêm thông tin ảnh hưởng chi phí vận tải trên bản đồ:
• Cập nhật thời tiết theo thời gian
• Cập nhật giá xăng dầu qua từng ngày
• Cập nhật màu sắc đường đi trên đoạn đường ùn tắc
• Cập nhật số lượng trạm thu phí trên suốt đường đi
• Cập nhật bản giá vận chuyển cụ thể cho từng Tỉnh
Mô hình đề xuất cho phép người dùng truy cập vào một ứng dụng duy nhất để nhận biết nhiều thông tin về giao thông, bao gồm thời gian di chuyển giữa các điểm, mật độ giao thông hiện tại, và gợi ý tuyến đường thay thế khi tuyến đường ngắn nhất gặp tình trạng tắc nghẽn hoặc tai nạn Điều này giúp người dùng kịp thời điều chỉnh lộ trình của mình.
Việc mở rộng mô hình địa điểm là cần thiết để tăng cường sự đa dạng, không chỉ giới hạn ở miền Đông Bắc Việt Nam Chúng ta có thể mang đến cho người dùng nhiều lựa chọn hơn từ khắp các tỉnh thành trên cả nước, với mỗi tỉnh thành cung cấp nhiều điểm đến để người dùng thoải mái lựa chọn.
Toàn b mã ngu n có th ộ ồ ể được tìm th y t i ấ ạ Link Github
Viết Hướ ng D ẫn Cách Cài Đặt Để Chạy
Bước 1: Truy c ập vào đườ ng Link Github để xem dự án nhóm đã tải lên
Bước 2: T ải chương trình bằ ng cách làm theo hình sau:
Sau khi n vào Download ZIP, vào ph n Download c a trình duy ấ ầ ủ ệt để kiểm tra
Sau khi tải xong tệp, hãy truy cập vào thư mục lưu trữ bằng cách nhấn vào "Hiển thị" trên trình duyệt Tại đây, nhấp chuột phải vào thư mục và chọn "Extract files" để giải nén thư mục.
Sau kh i ấ n vào Extract files s hi n lên c a s ẽ ệ ử ổ như sau:
Bạn có thể thay đổi đường dẫn đến tệp sau khi giải nén Sau khi điều chỉnh xong, hãy chọn “OK” để bắt đầu quá trình giải nén.
Bước 4: Sau khi gi i nén xong, t ả ại đị a ch b ỉ ạn đã đặt ở trên, s xu t hi ẽ ấ ện tệp tin như sau:
Nhấn chu t ph i vào file DoanDSA_UEH-main, ch n ti ộ ả ọ ếp cho đế n khi xu t hi ấ ện file Demo_Đồ_án như sau:
Chọn tiếp vào file Demo_Đồ _án - > Dikstra, cho đế n khi xu t hi ấ ện màn hình như thế này:
Chọn file Dijktra.exe để chạy d ự án
Cuối cùng chương trình xuất hiện
Hướng Phát Tri n ể
Đề xuất 1: Mô hình hiện tại chưa được trực quan, vì vậy chúng ta nên xây dựng đồ án dựa trên đường đi thực tế thay vì sử dụng đường thẳng Điều này sẽ giúp mô hình trở nên trực quan và tối ưu hơn Việc áp dụng đường thẳng trong đồ án thường phù hợp hơn với giao thông đường hàng không hoặc đường biển.
- Đề xuất 2: Thêm thông tin ảnh hưởng chi phí vận tải trên bản đồ:
• Cập nhật thời tiết theo thời gian
• Cập nhật giá xăng dầu qua từng ngày
• Cập nhật màu sắc đường đi trên đoạn đường ùn tắc
• Cập nhật số lượng trạm thu phí trên suốt đường đi
• Cập nhật bản giá vận chuyển cụ thể cho từng Tỉnh
Mô hình đề xuất có thể tích hợp nhiều yếu tố, cho phép người dùng truy cập thông tin giao thông đa dạng chỉ qua một ứng dụng Ứng dụng này cung cấp thời gian di chuyển giữa các điểm, mật độ giao thông, và gợi ý tuyến đường thay thế khi tuyến đường ngắn nhất gặp tình trạng ùn tắc hoặc tai nạn Điều này giúp người dùng kịp thời điều chỉnh lộ trình của mình.
Đề xuất mở rộng mô hình địa điểm là cần thiết để tăng cường sự đa dạng, không chỉ tập trung vào miền Đông Bắc Việt Nam Việc này sẽ mang đến cho người dùng nhiều sự lựa chọn hơn từ khắp các tỉnh thành, với nhiều điểm đến trong mỗi tỉnh, giúp họ thoải mái hơn trong việc lựa chọn.
Toàn b mã ngu n có th ộ ồ ể được tìm th y t i ấ ạ Link Github
Viết Hướ ng D ẫn Cách Cài Đặt Để Chạy
Bước 1: Truy c ập vào đườ ng Link Github để xem dự án nhóm đã tải lên
Bước 2: T ải chương trình bằ ng cách làm theo hình sau:
Sau khi n vào Download ZIP, vào ph n Download c a trình duy ấ ầ ủ ệt để kiểm tra
Sau khi tải xong tệp, bạn cần truy cập vào vị trí lưu trữ của tệp đó Bạn có thể nhấn vào tùy chọn "Hiển thị" trong thư mục trên trình duyệt để đến nơi lưu trữ Tại đây, hãy nhấp chuột phải vào thư mục và chọn "Extract files" để giải nén nội dung thư mục.
Sau kh i ấ n vào Extract files s hi n lên c a s ẽ ệ ử ổ như sau:
Bạn có thể thay đổi đường dẫn của tệp sau khi được giải nén bằng cách điều chỉnh đường dẫn đích Sau khi hoàn tất điều chỉnh, hãy chọn “OK” để bắt đầu quá trình giải nén.
Bước 4: Sau khi gi i nén xong, t ả ại đị a ch b ỉ ạn đã đặt ở trên, s xu t hi ẽ ấ ện tệp tin như sau:
Nhấn chu t ph i vào file DoanDSA_UEH-main, ch n ti ộ ả ọ ếp cho đế n khi xu t hi ấ ện file Demo_Đồ_án như sau:
Chọn tiếp vào file Demo_Đồ _án - > Dikstra, cho đế n khi xu t hi ấ ện màn hình như thế này:
Chọn file Dijktra.exe để chạy d ự án
Cuối cùng chương trình xuất hiện