×

Cài đặt thuật toán Floyd-Warshall trong lập trình

Thuật toán Floyd-Warshall là một trong những thuật toán kinh điển trong lý thuyết đồ thị, giúp tìm đường đi ngắn nhất giữa mọi cặp đỉnh trong một đồ thị có trọng số. Thuật toán này đặc biệt thích hợp cho các đồ thị có số lượng đỉnh không quá lớn vì độ phức tạp về thời gian của nó là (O(n^3)) với (n) là số lượng đỉnh.

Nguyên lý hoạt động

Thuật toán Floyd-Warshall sử dụng kỹ thuật lập trình động để cải tiến dần các khoảng cách giữa các cặp đỉnh, phiên dịch thành việc cập nhật ma trận trọng số của đồ thị. Ma trận trọng số (D) ban đầu chứa các giá trị khoảng cách trực tiếp giữa các cặp đỉnh. Với mỗi đỉnh (k) trung gian, chúng ta sẽ cập nhật ma trận (D) để xem liệu việc đi qua đỉnh (k) có thể rút ngắn khoảng cách giữa hai đỉnh (i) và (j) hay không.

Pseudocode của thuật toán

Pseudocode dưới đây minh hoạ quá trình cài đặt thuật toán Floyd-Warshall. Giả sử đồ thị được biểu diễn dưới dạng ma trận trọng số (D), trong đó (D[i][j]) đại diện cho trọng số cạnh từ đỉnh (i) đến đỉnh (j). Nếu không có cạnh trực tiếp giữa (i) và (j), (D[i][j]) sẽ có giá trị vô cùng.

for k from 1 to n:
    for i from 1 to n:
        for j from 1 to n:
            if D[i][j] > D[i][k] + D[k][j]:
                D[i][j] = D[i][k] + D[k][j]

Ví dụ

Xét ví dụ sau, chúng ta có đồ thị với 4 đỉnh với ma trận trọng số ban đầu được biểu diễn như sau:

     0     3   ∞   5
     2     0   ∞   4
    ∞      1   0   ∞
    ∞      ∞   2   0

Áp dụng thuật toán Floyd-Warshall, chúng ta sẽ lần lượt cập nhật ma trận trọng số này thông qua từng đỉnh trung gian. Kết quả cuối cùng sẽ cho chúng ta ma trận trọng số với khoảng cách ngắn nhất giữa mọi cặp đỉnh.

Cài đặt trong ngôn ngữ Python

Dưới đây là một ví dụ cài đặt thuật toán Floyd-Warshall bằng ngôn ngữ lập trình Python:

INF = float('inf')

def floyd_warshall(graph):
    dist = list(map(lambda i: list(map(lambda j: j, i)), graph))
    V = len(graph)

    for k in range(V):
        for i in range(V):
            for j in range(V):
                if dist[i][j] > dist[i][k] + dist[k][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]

    return dist

# Ví dụ đồ thị
graph = [[0, 3, INF, 5],
         [2, 0, INF, 4],
         [INF, 1, 0, INF],
         [INF, INF, 2, 0]]

# Chạy thuật toán
distance = floyd_warshall(graph)

# In ma trận khoảng cách ngắn nhất
for row in distance:
    print(row)

Ưu và nhược điểm

Ưu điểm:

  1. Toàn diện: Thuật toán này tính toán đường đi ngắn nhất giữa tất cả các cặp đỉnh.
  2. Đơn giản: Dễ dàng cài đặt và hiểu nguyên lý hoạt động.

Nhược điểm:

  1. Hiệu suất: Độ phức tạp thời gian là (O(n^3)), điều này có thể không hiệu quả cho các đồ thị lớn.
  2. Bộ nhớ: Cần sử dụng ma trận (n \times n) để lưu trữ khoảng cách, yêu cầu bộ nhớ (O(n^2)).

Ứng dụng trong thực tế

Thuật toán Floyd-Warshall thường được sử dụng trong các ứng dụng yêu cầu tính toán đường đi ngắn nhất giữa tất cả các cặp đỉnh trong đồ thị. Một số ví dụ bao gồm:

  • Mạng máy tính: Tìm đường đi ngắn nhất giữa các nút trong mạng.
  • Giao thông đô thị: Tính toán khoảng cách ngắn nhất giữa các điểm giao thông.
  • Mạng lưới phân phối: Tối ưu hóa đường đi cho việc giao hàng hoặc dịch vụ.

Tóm lại, thuật toán Floyd-Warshall là một công cụ mạnh mẽ và linh hoạt cho việc xử lý các bài toán đường đi ngắn nhất trong đồ thị, dù yêu cầu về thời gian và bộ nhớ của nó có thể hạn chế trong các ứng dụng lớn.

Comments