Tôi có một lưới các ô có kích thước hữu hạn đã biết tạo thành bản đồ. Một số gạch bên trong bản đồ được đặt vào một tập hợp được gọi là lãnh thổ. Lãnh thổ này được kết nối, nhưng không có gì được biết về hình dạng của nó. Hầu hết thời gian nó sẽ là một đốm màu khá đều đặn, nhưng nó có thể rất dài theo một hướng, và nó thậm chí có thể có lỗ hổng. Tôi quan tâm đến việc tìm ra biên giới (bên ngoài) của lãnh thổ.
Đó là, tôi muốn một danh sách tất cả các ô chạm vào một trong các ô trong lãnh thổ mà không nằm trong lãnh thổ. Một cách hiệu quả để tìm thấy điều này là gì?
Đối với khó khăn thêm, điều đó xảy ra là các ô của tôi là hình lục giác, nhưng tôi nghi ngờ điều này không tạo ra quá nhiều sự khác biệt, mỗi ô vẫn được gắn nhãn với tọa độ x và y và, được cung cấp một ô, tôi có thể dễ dàng tìm thấy các hàng xóm của nó. Dưới đây là một vài ví dụ: Màu đen là lãnh thổ và màu xanh là đường viền tôi muốn tìm. Bản thân điều này không phải là một vấn đề khó, Một thuật toán đơn giản cho điều này, trong giả hành, là:
def find_border_of_territory(territory):
border = []
for tile in territory:
for neighbor in tile.neighbors():
if neighbor not in territory and neighbor not in border:
border.add(neighbor)
Tuy nhiên điều này là chậm và tôi muốn một cái gì đó tốt hơn. Tôi có một vòng lặp O (n) trên lãnh thổ, một vòng lặp khác (một đoạn ngắn, nhưng vẫn) trên tất cả các hàng xóm và sau đó tôi phải kiểm tra tư cách thành viên qua hai danh sách, một trong số đó có kích thước n. Điều đó mang lại một tỷ lệ khủng khiếp của O (n ^ 2). Tôi có thể giảm điều đó xuống O (n) bằng cách sử dụng các tập hợp thay vì danh sách cho đường viền và lãnh thổ để kiểm tra tư cách thành viên nhanh chóng, nhưng nó vẫn không tuyệt vời. Tôi hy vọng sẽ có nhiều trường hợp lãnh thổ rộng nhưng biên giới nhỏ do diện tích đơn giản so với tỷ lệ đường. Ví dụ: nếu lãnh thổ là một hình lục giác có bán kính 5, nó có kích thước 91 nhưng đường viền chỉ có kích thước 36.
Bất cứ ai có thể đề xuất một cái gì đó tốt hơn?
Biên tập:
Để trả lời một số câu hỏi dưới đây. Lãnh thổ có thể có kích thước, từ khoảng 20 đến 100 hoặc hơn. Tập hợp các ô hình thành lãnh thổ là một thuộc tính của một đối tượng và đối tượng này cần một tập hợp tất cả các ô viền.
Ban đầu, lãnh thổ được tạo thành một khối, và sau đó chủ yếu giành được từng viên một. Trong trường hợp này, đúng là cách nhanh nhất chỉ là giữ một bộ đường viền và chỉ cập nhật nó trên ô có được. Đôi khi, một sự thay đổi lớn đối với lãnh thổ có thể xảy ra - vì vậy nó sẽ cần được tính toán lại đầy đủ sau đó.
Bây giờ tôi cho rằng làm một thuật toán tìm đường viền đơn giản là giải pháp tốt nhất. Sự phức tạp bổ sung duy nhất mà điều này tăng lên là để đảm bảo rằng đường viền được tính toán lại mỗi lần nó có thể cần, nhưng không nhiều hơn thế. Tôi khá tự tin rằng điều này có thể được thực hiện một cách đáng tin cậy trong khuôn khổ hiện tại của tôi.
Về thời gian, trong mã hiện tại của tôi, tôi có một số thói quen cần kiểm tra mọi ô của lãnh thổ. Không phải mỗi lượt, nhưng về sáng tạo và đôi khi sau đó. Điều đó chiếm hơn 50% thời gian chạy bộ mã kiểm tra của tôi mặc dù đó là một phần rất nhỏ của chương trình hoàn chỉnh. Do đó tôi rất muốn giảm thiểu bất kỳ sự lặp lại. TUY NHIÊN, mã kiểm tra liên quan đến việc tạo đối tượng nhiều hơn so với việc chạy chương trình bình thường (một cách tự nhiên), vì vậy tôi nhận ra điều này có thể không liên quan lắm.