Chi phí tối thiểu để kết nối tất cả các đảo là bao nhiêu?


84

Có một mạng lưới các kích thước N x M . Một số ô là các hòn đảo được ký hiệu bằng '0' và các ô khác là nước . Mỗi ô nước có một số trên đó biểu thị chi phí của một cây cầu được thực hiện trên ô đó. Bạn phải tìm chi phí tối thiểu mà tất cả các đảo có thể được kết nối. Một ô được kết nối với một ô khác nếu nó chia sẻ một cạnh hoặc một đỉnh.

Thuật toán nào có thể được sử dụng để giải quyết vấn đề này? Điều gì có thể được sử dụng như một phương pháp tiếp cận vũ phu nếu các giá trị của N, M là rất nhỏ, giả sử NxM <= 100?

Ví dụ : Trong hình đã cho, các ô màu xanh lá cây biểu thị các hòn đảo, các ô màu xanh lam biểu thị nước và các ô màu xanh lam nhạt cho biết các ô mà trên đó sẽ làm một cây cầu. Vì vậy, đối với hình ảnh sau đây, câu trả lời sẽ là 17 .

http://i.imgur.com/ClcboBy.png

Ban đầu tôi nghĩ đến việc đánh dấu tất cả các hòn đảo là các điểm nút và kết nối mọi cặp đảo bằng một cây cầu ngắn nhất. Sau đó, vấn đề có thể được giảm xuống cây khung tối thiểu, nhưng trong cách tiếp cận này, tôi đã bỏ qua trường hợp các cạnh chồng lên nhau. Ví dụ , trong hình ảnh sau, khoảng cách ngắn nhất giữa hai hòn đảo bất kỳ là 7 (được đánh dấu bằng màu vàng), vì vậy bằng cách sử dụng Cây có khoảng cách tối thiểu, câu trả lời sẽ là 14 , nhưng câu trả lời phải là 11 (được đánh dấu bằng màu xanh nhạt).

image2


Cách tiếp cận giải pháp bạn đã mô tả trong các câu hỏi của mình có vẻ đúng. Bạn có thể giải thích thêm về ý của bạn khi "Tôi đã bỏ qua trường hợp các cạnh chồng lên nhau" không?
Asad Saeeduddin

@Asad: Tôi đã thêm một hình ảnh để giải thích vấn đề trong cách tiếp cận MST.
Atul Vaibhav,

"kết nối hai hòn đảo bằng một cây cầu ngắn nhất" - như bạn có thể thấy, đó rõ ràng là một cách tiếp cận tồi.
Karoly Horvath,

1
Bạn có thể vui lòng chia sẻ mã bạn hiện đang sử dụng không? Điều này sẽ giúp đưa ra câu trả lời dễ dàng hơn một chút và cũng sẽ cho chúng tôi biết chính xác cách tiếp cận hiện tại của bạn là gì.
Asad Saeeduddin

7
Đây là một biến thể của vấn đề cây Steiner . Theo liên kết tới Wikipedia để biết thêm thông tin chi tiết. Nói tóm lại, có lẽ không thể tìm ra lời giải chính xác trong thời gian đa thức, nhưng cây bao trùm tối thiểu là một phép gần đúng không tệ.
Gassa,

Câu trả lời:


67

Để tiếp cận vấn đề này, tôi sẽ sử dụng một khung lập trình số nguyên và xác định ba bộ biến quyết định:

  • x_ij : Một biến chỉ báo nhị phân về việc chúng ta có xây dựng một cây cầu ở vị trí nước hay không (i, j).
  • y_ijbcn : Một chỉ số nhị phân cho biết vị trí nước (i, j) có phải là vị trí thứ n nối đảo b với đảo c hay không.
  • l_bc : Một biến chỉ báo nhị phân cho biết các đảo b và c có được liên kết trực tiếp hay không (bạn chỉ có thể đi bộ trên các ô cầu từ b đến c).

Đối với chi phí xây dựng cầu c_ij , giá trị mục tiêu cần giảm thiểu là sum_ij c_ij * x_ij. Chúng ta cần thêm các ràng buộc sau vào mô hình:

  • Chúng ta cần đảm bảo các biến y_ijbcn là hợp lệ. Chúng ta luôn chỉ có thể đến được một quảng trường nước nếu chúng ta xây một cây cầu ở đó, vì vậy y_ijbcn <= x_ijđối với mọi vị trí nước (i, j). Hơn nữa, y_ijbc1phải bằng 0 nếu (i, j) không biên giới với đảo b. Cuối cùng, với n> 1,y_ijbcn chỉ có thể được sử dụng nếu vị trí nước lân cận đã được sử dụng trong bước n-1. Định nghĩa N(i, j)là các bình phương nước lân cận (i, j), điều này tương đương với y_ijbcn <= sum_{(l, m) in N(i, j)} y_lmbc(n-1).
  • Chúng tôi cần đảm bảo biến l_bc chỉ được đặt nếu b và c được liên kết. Nếu chúng tôi xác định I(c)là các vị trí giáp với đảo c, điều này có thể được thực hiện với l_bc <= sum_{(i, j) in I(c), n} y_ijbcn.
  • Chúng ta cần đảm bảo rằng tất cả các đảo đều được liên kết, trực tiếp hoặc gián tiếp. Điều này có thể được thực hiện theo cách sau: đối với mỗi tập hợp con S các đảo thích hợp không trống, yêu cầu rằng ít nhất một đảo trong S được liên kết với ít nhất một đảo trong phần bổ sung của S, mà chúng ta sẽ gọi là S '. Trong các ràng buộc, chúng ta có thể thực hiện điều này bằng cách thêm một ràng buộc cho mọi tập không rỗng S có kích thước <= K / 2 (với K là số đảo) , sum_{b in S} sum_{c in S'} l_bc >= 1.

Đối với một ví dụ bài toán với K đảo, W hình vuông nước và độ dài đường dẫn tối đa được chỉ định N, đây là một mô hình lập trình số nguyên hỗn hợp với O(K^2WN)các biến và O(K^2WN + 2^K)ràng buộc. Rõ ràng là điều này sẽ trở nên khó chữa khi kích thước vấn đề trở nên lớn, nhưng nó có thể giải quyết được đối với các kích thước bạn quan tâm. Để hiểu về khả năng mở rộng, tôi sẽ triển khai nó trong python bằng cách sử dụng gói bột giấy. Trước tiên, hãy bắt đầu với bản đồ 7 x 9 nhỏ hơn với 3 hòn đảo ở cuối câu hỏi:

import itertools
import pulp
water = {(0, 2): 2.0, (0, 3): 1.0, (0, 4): 1.0, (0, 5): 1.0, (0, 6): 2.0,
         (1, 0): 2.0, (1, 1): 9.0, (1, 2): 1.0, (1, 3): 9.0, (1, 4): 9.0,
         (1, 5): 9.0, (1, 6): 1.0, (1, 7): 9.0, (1, 8): 2.0,
         (2, 0): 1.0, (2, 1): 9.0, (2, 2): 9.0, (2, 3): 1.0, (2, 4): 9.0,
         (2, 5): 1.0, (2, 6): 9.0, (2, 7): 9.0, (2, 8): 1.0,
         (3, 0): 9.0, (3, 1): 1.0, (3, 2): 9.0, (3, 3): 9.0, (3, 4): 5.0,
         (3, 5): 9.0, (3, 6): 9.0, (3, 7): 1.0, (3, 8): 9.0,
         (4, 0): 9.0, (4, 1): 9.0, (4, 2): 1.0, (4, 3): 9.0, (4, 4): 1.0,
         (4, 5): 9.0, (4, 6): 1.0, (4, 7): 9.0, (4, 8): 9.0,
         (5, 0): 9.0, (5, 1): 9.0, (5, 2): 9.0, (5, 3): 2.0, (5, 4): 1.0,
         (5, 5): 2.0, (5, 6): 9.0, (5, 7): 9.0, (5, 8): 9.0,
         (6, 0): 9.0, (6, 1): 9.0, (6, 2): 9.0, (6, 6): 9.0, (6, 7): 9.0,
         (6, 8): 9.0}
islands = {0: [(0, 0), (0, 1)], 1: [(0, 7), (0, 8)], 2: [(6, 3), (6, 4), (6, 5)]}
N = 6

# Island borders
iborders = {}
for k in islands:
    iborders[k] = {}
    for i, j in islands[k]:
        for dx in [-1, 0, 1]:
            for dy in [-1, 0, 1]:
                if (i+dx, j+dy) in water:
                    iborders[k][(i+dx, j+dy)] = True

# Create models with specified variables
x = pulp.LpVariable.dicts("x", water.keys(), lowBound=0, upBound=1, cat=pulp.LpInteger)
pairs = [(b, c) for b in islands for c in islands if b < c]
yvals = []
for i, j in water:
    for b, c in pairs:
        for n in range(N):
            yvals.append((i, j, b, c, n))

y = pulp.LpVariable.dicts("y", yvals, lowBound=0, upBound=1)
l = pulp.LpVariable.dicts("l", pairs, lowBound=0, upBound=1)
mod = pulp.LpProblem("Islands", pulp.LpMinimize)

# Objective
mod += sum([water[k] * x[k] for k in water])

# Valid y
for k in yvals:
    i, j, b, c, n = k
    mod += y[k] <= x[(i, j)]
    if n == 0 and not (i, j) in iborders[b]:
        mod += y[k] == 0
    elif n > 0:
        mod += y[k] <= sum([y[(i+dx, j+dy, b, c, n-1)] for dx in [-1, 0, 1] for dy in [-1, 0, 1] if (i+dx, j+dy) in water])

# Valid l
for b, c in pairs:
    mod += l[(b, c)] <= sum([y[(i, j, B, C, n)] for i, j, B, C, n in yvals if (i, j) in iborders[c] and B==b and C==c])

# All islands connected (directly or indirectly)
ikeys = islands.keys()
for size in range(1, len(ikeys)/2+1):
    for S in itertools.combinations(ikeys, size):
        thisSubset = {m: True for m in S}
        Sprime = [m for m in ikeys if not m in thisSubset]
        mod += sum([l[(min(b, c), max(b, c))] for b in S for c in Sprime]) >= 1

# Solve and output
mod.solve()
for row in range(min([m[0] for m in water]), max([m[0] for m in water])+1):
    for col in range(min([m[1] for m in water]), max([m[1] for m in water])+1):
        if (row, col) in water:
            if x[(row, col)].value() > 0.999:
                print "B",
            else:
                print "-",
        else:
            print "I",
    print ""

Quá trình này mất 1,4 giây để chạy bằng bộ giải mặc định từ gói bột giấy (bộ giải CBC) và xuất ra giải pháp chính xác:

I I - - - - - I I 
- - B - - - B - - 
- - - B - B - - - 
- - - - B - - - - 
- - - - B - - - - 
- - - - B - - - - 
- - - I I I - - - 

Tiếp theo, hãy xem xét vấn đề đầy đủ ở đầu câu hỏi, đó là lưới 13 x 14 với 7 hòn đảo:

water = {(i, j): 1.0 for i in range(13) for j in range(14)}
islands = {0: [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)],
           1: [(9, 0), (9, 1), (10, 0), (10, 1), (10, 2), (11, 0), (11, 1),
               (11, 2), (12, 0)],
           2: [(0, 7), (0, 8), (1, 7), (1, 8), (2, 7)],
           3: [(7, 7), (8, 6), (8, 7), (8, 8), (9, 7)],
           4: [(0, 11), (0, 12), (0, 13), (1, 12)],
           5: [(4, 10), (4, 11), (5, 10), (5, 11)],
           6: [(11, 8), (11, 9), (11, 13), (12, 8), (12, 9), (12, 10), (12, 11),
               (12, 12), (12, 13)]}
for k in islands:
    for i, j in islands[k]:
        del water[(i, j)]

for i, j in [(10, 7), (10, 8), (10, 9), (10, 10), (10, 11), (10, 12),
             (11, 7), (12, 7)]:
    water[(i, j)] = 20.0

N = 7

Những người giải MIP thường có được các giải pháp tốt tương đối nhanh chóng và sau đó dành một khoảng thời gian rất lớn để cố gắng chứng minh tính tối ưu của giải pháp. Sử dụng mã bộ giải tương tự như trên, chương trình không hoàn thành trong vòng 30 phút. Tuy nhiên, bạn có thể cung cấp thời gian chờ cho bộ giải để có được giải pháp gần đúng:

mod.solve(pulp.solvers.PULP_CBC_CMD(maxSeconds=120))

Điều này mang lại một giải pháp với giá trị mục tiêu 17:

I I - - - - - I I - - I I I 
I I - - - - - I I - - - I - 
I I - - - - - I - B - B - - 
- - B - - - B - - - B - - - 
- - - B - B - - - - I I - - 
- - - - B - - - - - I I - - 
- - - - - B - - - - - B - - 
- - - - - B - I - - - - B - 
- - - - B - I I I - - B - - 
I I - B - - - I - - - - B - 
I I I - - - - - - - - - - B 
I I I - - - - - I I - - - I 
I - - - - - - - I I I I I I 

Để cải thiện chất lượng của các giải pháp bạn nhận được, bạn có thể sử dụng trình giải MIP thương mại (điều này miễn phí nếu bạn đang ở một cơ sở giáo dục và có thể không miễn phí nếu không). Ví dụ: đây là hiệu suất của Gurobi 6.0.4, một lần nữa với giới hạn thời gian 2 phút (mặc dù từ nhật ký giải pháp, chúng tôi đọc rằng trình giải đã tìm thấy giải pháp tốt nhất hiện tại trong vòng 7 giây):

mod.solve(pulp.solvers.GUROBI(timeLimit=120))

Điều này thực sự tìm thấy một giải pháp có giá trị mục tiêu 16, một giải pháp tốt hơn so với OP có thể tìm thấy bằng tay!

I I - - - - - I I - - I I I 
I I - - - - - I I - - - I - 
I I - - - - - I - B - B - - 
- - B - - - - - - - B - - - 
- - - B - - - - - - I I - - 
- - - - B - - - - - I I - - 
- - - - - B - - B B - - - - 
- - - - - B - I - - B - - - 
- - - - B - I I I - - B - - 
I I - B - - - I - - - - B - 
I I I - - - - - - - - - - B 
I I I - - - - - I I - - - I 
I - - - - - - - I I I I I I 

Thay vì công thức y_ijbcn, tôi sẽ thử một công thức dựa trên dòng chảy (biến cho mỗi bộ bao gồm một cặp đảo và kề vuông; các ràng buộc bảo toàn, với phần dư thừa 1 ở bồn rửa và -1 ở nguồn; tổng dòng chảy bị ràng buộc tại một hình vuông xem nó đã được mua hay chưa).
David Eisenstat

1
@DavidEisenstat cảm ơn bạn đã đề xuất - Tôi vừa mới dùng thử và rất tiếc là nó đã giải quyết chậm hơn cho các trường hợp sự cố này.
josliber

8
Đây chính xác là những gì tôi đã tìm kiếm khi bắt đầu tiền thưởng. Nó làm tôi ngạc nhiên làm thế nào mà một vấn đề tầm thường khó mô tả lại có thể gây khó khăn cho người giải MIP như vậy. Tôi đã tự hỏi liệu điều sau có đúng không: Một đường dẫn liên kết hai hòn đảo là đường dẫn ngắn nhất với ràng buộc bổ sung rằng nó phải đi qua một số ô (i, j). Ví dụ, các đảo trên cùng bên trái và giữa trong giải pháp của Gurobi được liên kết với một SP bị hạn chế đi qua ô (6, 5). Không chắc liệu điều này có đúng không, nhưng hãy nhìn vào nó vào một lúc nào đó. Cảm ơn vì câu trả lời!
Ioannis

@Ioannis câu hỏi thú vị - Tôi không chắc liệu phỏng đoán của bạn có đúng không nhưng nó có vẻ khá hợp lý với tôi. Bạn có thể nghĩ về ô (i, j) là nơi những cây cầu từ những hòn đảo này cần đi để kết nối xa hơn với các hòn đảo khác, và sau đó tùy thuộc vào điểm điều phối đó, bạn sẽ chỉ muốn xây những cây cầu rẻ nhất có thể để kết nối hòn đảo đôi.
josliber

5

Một cách tiếp cận vũ phu, trong mã giả:

start with a horrible "best" answer
given an nxm map,
    try all 2^(n*m) combinations of bridge/no-bridge for each cell
        if the result is connected, and better than previous best, store it

return best

Trong C ++, điều này có thể được viết là

// map = linearized map; map[x*n + y] is the equivalent of map2d[y][x]
// nm = n*m
// bridged = true if bridge there, false if not. Also linearized
// nBridged = depth of recursion (= current bridge being considered)
// cost = total cost of bridges in 'bridged'
// best, bestCost = best answer so far. Initialized to "horrible"
void findBestBridges(char map[], int nm,
   bool bridged[], int nBridged, int cost, bool best[], int &bestCost) {
   if (nBridged == nm) {
      if (connected(map, nm, bridged) && cost < bestCost) {
          memcpy(best, bridged, nBridged);
          bestCost = best;
      }
      return;
   }
   if (map[nBridged] != 0) {
      // try with a bridge there
      bridged[nBridged] = true;
      cost += map[nBridged];

      // see how it turns out
      findBestBridges(map, nm, bridged, nBridged+1, cost, best, bestCost);         

      // remove bridge for further recursion
      bridged[nBridged] = false;
      cost -= map[nBridged];
   }
   // and try without a bridge there
   findBestBridges(map, nm, bridged, nBridged+1, cost, best, bestCost);
}

Sau khi thực hiện cuộc gọi đầu tiên (tôi giả sử bạn đang chuyển đổi bản đồ 2d của mình thành mảng 1d để dễ dàng sao chép xung quanh), bestCostsẽ chứa chi phí của câu trả lời tốt nhất và bestsẽ chứa mẫu cầu tạo ra nó. Tuy nhiên, điều này cực kỳ chậm.

Tối ưu hóa:

  • Bằng cách sử dụng "giới hạn cầu" và chạy thuật toán để tăng số cầu tối đa, bạn có thể tìm thấy các câu trả lời tối thiểu mà không cần khám phá toàn bộ cây. Tìm câu trả lời 1 cầu, nếu nó tồn tại, sẽ là O (nm) thay vì O (2 ^ nm) - một cải tiến mạnh mẽ.
  • Bạn có thể tránh tìm kiếm (bằng cách dừng đệ quy; điều này còn được gọi là "cắt tỉa") khi bạn đã vượt quá bestCost, bởi vì việc tiếp tục tìm kiếm sau đó sẽ không có ý nghĩa gì. Nếu nó không thể trở nên tốt hơn, đừng tiếp tục đào.
  • Việc cắt tỉa ở trên hoạt động tốt hơn nếu bạn nhìn vào các ứng cử viên "tốt" trước khi xem xét các ứng cử viên "xấu" (vì nó là tất cả các ô được xem xét theo thứ tự từ trái sang phải, từ trên xuống dưới). Một phương pháp heuristic tốt sẽ là coi các ô ở gần một số thành phần không được kết nối là có mức độ ưu tiên cao hơn các ô không có. Tuy nhiên, khi bạn thêm heuristics, tìm kiếm của bạn bắt đầu giống A * (và bạn cũng cần một số loại hàng đợi ưu tiên).
  • Những cây cầu trùng lặp và những cây cầu không đến nơi đến chốn là điều không thể tránh khỏi. Bất kỳ cầu nối nào không ngắt kết nối mạng đảo nếu bị loại bỏ là thừa.

Một thuật toán tìm kiếm chung như A * cho phép tìm kiếm nhanh hơn nhiều, mặc dù việc tìm kiếm phương pháp heuristics tốt hơn không phải là một nhiệm vụ đơn giản. Đối với một cách tiếp cận vấn đề cụ thể hơn, sử dụng các kết quả hiện có trên cây Steiner , như được đề xuất bởi @Gassa, là cách để đi. Tuy nhiên, lưu ý rằng vấn đề xây dựng cây Steiner trên lưới trực giao là NP-Complete, theo bài báo này của Garey và Johnson .

Nếu "đủ tốt" là đủ, một thuật toán di truyền có thể nhanh chóng tìm ra các giải pháp có thể chấp nhận được, miễn là bạn thêm một vài kinh nghiệm quan trọng vào vị trí cầu được ưu tiên.


"thử tất cả các kết hợp 2 ^ (n * m)" uh, 2^(13*14) ~ 6.1299822e+54lặp lại. Nếu chúng tôi giả sử bạn có thể thực hiện một triệu lần lặp mỗi giây, điều đó sẽ chỉ mất ... ~ 194380460000000000000000000000000000000000` năm. Những tối ưu hóa đó là rất cần thiết.
Vịt rên rỉ vào

OP đã yêu cầu "một cách tiếp cận bạo lực nếu các giá trị của N, M rất nhỏ, giả sử NxM <= 100". Giả sử, 20 cầu nối là đủ và cách tối ưu hóa duy nhất bạn sử dụng là giới hạn cầu ở trên, giải pháp tối ưu sẽ được tìm thấy ở O (2 ^ 20), nằm trong phạm vi máy tính giả định của bạn.
tucuxi

Hầu hết các thuật toán backtracking đều kém hiệu quả một cách khủng khiếp cho đến khi bạn thêm cắt tỉa, đào sâu lặp đi lặp lại, v.v. Điều này không có nghĩa là chúng vô dụng. Ví dụ, động cơ cờ thường xuyên đánh bại kiện tướng với các thuật toán (cấp - họ sử dụng mọi thủ đoạn trong cuốn sách để prune tích cực)
cá heo tucuxi

3

Bài toán này là một biến thể của cây Steiner được gọi là cây Steiner trọng số nút , chuyên biệt hóa một loại đồ thị nhất định. Nói một cách ngắn gọn, cây Steiner có trọng số nút, được đưa ra một đồ thị vô hướng có trọng số nút trong đó một số nút là thiết bị đầu cuối, tìm tập hợp các nút rẻ nhất bao gồm tất cả các thiết bị đầu cuối tạo ra một đồ thị con được kết nối. Đáng buồn thay, tôi dường như không thể tìm thấy bất kỳ bộ giải nào trong một số tìm kiếm lướt qua.

Để xây dựng dưới dạng một chương trình số nguyên, hãy tạo một biến 0-1 cho mỗi nút không phải đầu cuối, sau đó cho tất cả các tập con của các nút không phải đầu cuối mà việc loại bỏ khỏi đồ thị bắt đầu sẽ ngắt kết nối hai đầu cuối, yêu cầu tổng các biến trong tập hợp con phải bằng ít nhất là 1. Điều này gây ra quá nhiều ràng buộc, vì vậy bạn sẽ phải thực thi chúng một cách lười biếng, sử dụng một thuật toán hiệu quả cho kết nối nút (về cơ bản là luồng tối đa) để phát hiện một ràng buộc bị vi phạm tối đa. Xin lỗi vì thiếu chi tiết, nhưng đây sẽ là một khó khăn để thực hiện ngay cả khi bạn đã quen với lập trình số nguyên.


-1

Giả sử rằng vấn đề này diễn ra trong một lưới và bạn đã xác định rõ các tham số, tôi sẽ tiếp cận vấn đề với việc loại bỏ một cách có hệ thống không gian bài toán thông qua việc tạo một cây bao trùm tối thiểu. Khi làm như vậy, tôi thấy có ý nghĩa nếu bạn tiếp cận vấn đề này với Thuật toán Prim.

Thật không may, bây giờ bạn gặp phải vấn đề trừu tượng hóa lưới để tạo một tập hợp các nút và cạnh ... vấn đề thực sự của bài đăng này là làm cách nào để chuyển đổi lưới nxm của tôi thành {V} và {E}?

Trong nháy mắt, quá trình chuyển đổi này có thể là NP-Khó vì có thể có số lượng kết hợp tuyệt đối (giả sử rằng tất cả các chi phí đường thủy đều giống nhau). Để xử lý các trường hợp các đường dẫn chồng chéo lên nhau, bạn nên cân nhắc tạo hòn đảo ảo.

Khi điều này được thực hiện, hãy chạy Thuật toán của Prim và bạn sẽ đi đến giải pháp tối ưu.

Tôi không tin rằng Lập trình động có thể chạy hiệu quả ở đây vì không có nguyên tắc tối ưu nào có thể quan sát được. Nếu chúng tôi tìm thấy chi phí tối thiểu giữa hai hòn đảo, điều đó không nhất thiết có nghĩa là chúng tôi có thể tìm thấy chi phí tối thiểu giữa hai hòn đảo đó và hòn đảo thứ ba, hoặc một tập hợp con khác của các hòn đảo sẽ là (theo định nghĩa của tôi là tìm MST qua Prim) được kết nối.

Nếu bạn muốn mã (giả hoặc cách khác) để chuyển đổi lưới của bạn thành một tập hợp {V} và {E}, vui lòng gửi cho tôi một tin nhắn riêng và tôi sẽ xem xét việc nối một triển khai với nhau.


Tất cả các chi phí nước không giống nhau (xem ví dụ). Vì Prim không có khái niệm về việc tạo các "nút ảo" đó, bạn nên xem xét một thuật toán thực hiện: Cây Steiner (nơi các nút ảo của bạn được gọi là "Điểm Steiner").
tucuxi

@tucuxi: Đề cập rằng tất cả các chi phí đường thủy thể giống nhau là cần thiết để phân tích trường hợp xấu nhất vì đây là điều kiện làm tăng không gian tìm kiếm đến mức tối đa tiềm năng của nó. Đây là lý do tại sao tôi đưa nó lên. Liên quan đến Prim, tôi giả sử rằng lập trình viên phụ trách triển khai Prim cho vấn đề này nhận ra rằng Prim không tạo các nút ảo và xử lý điều này ở cấp độ thực thi. Mình chưa thấy cây Steiner (còn đang học dở dang) nên cảm ơn bạn đã có tài liệu mới để tìm hiểu!
karnesJ.R
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.