Tìm hình dạng trong Mảng 2D, sau đó tối ưu hóa


11

Tôi vừa được cho phép một hình ảnh ... Hình ảnh bên dưới trong trò chơi của tôi cho thấy một số khối bị tối, được công nhận là một phần của hình chữ "T". Có thể thấy, mã đã làm tối các khối với các đốm đỏ và không nhìn thấy hình chữ "T" với các đường viền màu xanh lá cây.

Tìm thấy các mẫu mong muốn, nhưng chưa được tối ưu hóa

Mã của tôi lặp qua x / y, đánh dấu các khối là đã sử dụng, xoay hình dạng, lặp lại, thay đổi màu sắc, lặp lại.

Tôi đã bắt đầu cố gắng sửa chữa kiểm tra này với sự lo lắng lớn. Ý tưởng hiện tại là:

  • lặp qua lưới và ghi chú tất cả các lần xuất hiện của mẫu (KHÔNG đánh dấu các khối như đã sử dụng) và đặt chúng vào một mảng
  • lặp lại qua lưới một lần nữa, lần này lưu ý các khối nào bị chiếm bởi các mẫu nào và do đó chúng bị chiếm bởi nhiều mẫu.
  • lặp lại qua lưới lần nữa, lần này lưu ý mẫu nào cản trở mẫu nào

Điều đó cảm thấy rất đúng ... Tôi phải làm gì bây giờ?

Tôi nghĩ rằng tôi sẽ phải

  • thử kết hợp nhiều hình dạng xung đột khác nhau, bắt đầu với những hình dạng gây cản trở hầu hết các mẫu khác trước. Làm thế nào để tôi tiếp cận cái này?
  • sử dụng hợp lý nói rằng tôi có 3 hình dạng xung đột chiếm 8 khối và mỗi hình có 4 khối, do đó tôi chỉ có thể có tối đa hai hình.

(Tôi cũng có ý định kết hợp các hình dạng khác, và có thể sẽ có trọng số điểm cần được xem xét khi đi qua các hình dạng xung đột, nhưng đó có thể là một ngày khác)

Tôi không nghĩ đó là vấn đề về thùng rác, nhưng tôi không biết phải tìm gì. Hy vọng điều đó có ý nghĩa, nhờ sự giúp đỡ của bạn

EDIT Mặc dù rõ ràng về câu hỏi, mọi người dường như đã hiểu, vâng,

Tôi muốn tìm hình dạng chữ "T" tối đa trong mỗi màu

(bởi vì nếu tôi cho bạn hai điểm và bạn đã kiếm được ba điểm, bạn sẽ hơi khó chịu)


Một thuật toán tham lam coudld là chia bảng thành các tập hợp các khối đã tham gia. Sau đó, với mỗi bộ sưu tập, bạn có thể thử điền vào các hình dạng và cho điểm số phụ thuộc vào số lượng khối còn lại sẽ không bị tối. Kiểu khiến tôi nghĩ về en.wikipedia.org/wiki/Knapsack_propet .
Jonathan Connell

2
Tôi nghĩ rằng có một cái gì đó thiếu trong câu hỏi. Bạn có muốn tạo một thuật toán tìm càng nhiều nhóm hình chữ "T" càng tốt không?
Markus von Broady

Nếu tôi hiểu bạn thì bạn đang đi đúng hướng. Bạn không quá rõ ràng và tôi sẽ thích nó nếu bạn có thể giải thích.
AturSams

Câu trả lời:


3

Hãy để tôi xem nếu tôi hiểu đúng, các khối được đánh dấu màu đỏ, có màu xanh và thuật toán tìm thấy hình chữ T và đánh dấu chúng màu đỏ, điều đó có đúng không? Mục tiêu của bạn là tìm ra càng nhiều hình chữ T càng tốt với các khối cùng màu, chính xác cho đến nay tôi hy vọng. Hiện tại bạn đánh dấu chúng một khi bạn tìm thấy chúng và điều đó làm giảm tính hữu dụng của thuật toán (Vì bạn có thể thiếu giải pháp tối ưu). Bạn đang lên kế hoạch tìm kiếm tất cả các hình dạng và sau đó chọn hình nào sẽ sử dụng và hình nào không sử dụng. Tôi có đúng cho đến nay? Vì bạn muốn tối đa hóa số lượng khối được chứa bên trong hình chữ T khi thuật toán được thực hiện.

Nếu tôi đúng sau đây là giải pháp tối ưu cho tình huống của bạn theo ý kiến ​​của tôi.

Chúng tôi sẽ sử dụng lập trình tuyến tính Integer.

Tôi tin rằng tôi đã sử dụng cái này trong quá khứ:

http://sourceforge.net/projects/lpsolve/

http://lpsolve.sourceforge.net/5.5/Java/README.html

(Bạn có thể làm cho nó hoạt động với nhiều ngôn ngữ, tôi đã sử dụng nó với PHP, Java và C)

Những gì chúng ta sẽ làm là đăng ký mọi hình dạng T có thể có trên bảng và sau đó sử dụng ILP để tối đa hóa số lượng khối được bảo hiểm. ILP phức tạp theo cấp số nhân. Xem xét kích thước của bảng của bạn, đó sẽ không phải là một vấn đề. Tôi đã chạy các câu hỏi tối thiểu / tối thiểu phức tạp hơn nhiều trên các biểu đồ với ILP và chỉ mất một phần giây để hoàn thành và tối đa 30-90 giây với hàng trăm đỉnh (trong trường hợp của bạn, nó rơi vào một phần của giây).

Những gì tôi muốn giới thiệu để làm:

  1. Tìm tất cả các hình dạng đường có thể
  2. Tìm tất cả các giao điểm giữa các hình dạng đường cùng màu
  3. Tìm tất cả các hình dạng T có thể, tìm kiếm tất cả các giao lộ.
  4. Xác định một biến Boolean trong Bài toán tuyến tính cho mỗi hình dạng T (0 <= Bi <= 1 ) Vì các giá trị là số nguyên, để lại 0 hoặc 1.
  5. Tạo điều kiện cho mỗi cặp hình chữ T cắt nhau ( Bi + Bj <= 1)
  6. Hàm mục tiêu sẽ là (tổng các khối trong Hình dạng "T" (i) * Bi)
  7. Chạy bộ giải và làm tối các hình dạng T trong đó Boolean (s) tương ứng của bộ giải trong đó 1 trong giải pháp tối ưu.

Đây là kiến ​​thức có giá trị, tôi thường sử dụng bộ giải tuyến tính cho các dự án công việc.

ILP về cơ bản là một cách để giải quyết các vấn đề lựa chọn trong đó bạn muốn đạt được mức tối đa hoặc tối thiểu cho một số hàm tuyến tính.

Bạn có thể đọc thêm ở đây, sử dụng Lập trình tuyến tính Integer và Lập trình tuyến tính là giống nhau đối với người lập trình, chỉ có điều Integer phức tạp hơn nhiều đối với máy tính có thể dẫn đến thời gian chạy dài. Không phải trong trường hợp của bạn, nó rất đơn giản và chỉ mất ít hơn một phần nghìn giây trong trường hợp xấu nhất.

Tôi đoán bạn có thể đọc thêm ở đây:

http://en.wikipedia.org/wiki/Integer_linear_programming#Integer_unknowns

Điều này giải thích nó tốt:

http://fisher.osu.edu/~croxton_4/tutorial/

Nó về cơ bản là một người giải quyết vấn đề quyết định, làm thế nào để đưa ra quyết định tối đa hóa kết quả bạn muốn. Điều này giả định hàm đánh giá kết quả là tuyến tính trong trường hợp hiện tại cụ thể của bạn. Hàm đánh giá kết quả trong trường hợp này, tổng hợp các khối cho tất cả các hình dạng T mà bạn quyết định làm tối.

Về mặt toán học, cách đặt các biến: trong trường hợp hiện tại của chúng tôi Booleans (Tôi có làm tối hình dạng T với chỉ số i hay không) thành các giá trị tối ưu để tối đa hóa kết quả mà chúng tôi muốn: làm tối càng nhiều khối càng tốt mà không làm tối các hình chữ T giao nhau. Miễn là kết quả bạn muốn có thể được tính bằng hàm tuyến tính khi bạn có tất cả các biến được đặt, nó sẽ giải quyết nó. Trong trường hợp của chúng tôi, chúng tôi kiểm tra hình chữ T nào chúng tôi làm tối và tính tổng các khối mà chúng bao phủ.

nhập mô tả hình ảnh ở đây

Tôi biết điều này không tầm thường nên nếu bạn chọn thực hiện bước nhảy vọt, hãy bình luận và tôi sẽ giải thích.


Cảm ơn Arthur vì sự giúp đỡ của bạn. Nó có thể mất một vài lần đọc để tiêu hóa. Và vâng, bạn đã hiểu vấn đề chính xác. Tôi sẽ rất thích thú nếu bạn chuẩn bị công phu (không, không, nó không tầm thường), nhưng điều này sẽ giúp tôi đến nơi tôi sẽ đến!
Assembler

Ngôn ngữ nào bạn đang sử dụng để thực hiện?
AturSams

hành động 3! yêu thích của mọi người!
Assembler

tương tự ở đây Tôi sẽ viết một triển khai trong as3 và tải nó lên một github để tải xuống với lời bình luận, làm việc từng bước một - tôi có thể hoàn thành nó ngay hôm nay
AturSams

Bạn có bất kỳ khu vực cụ thể 1 -7 nơi bạn muốn tôi thêm ý kiến ​​hoặc công phu? btw, tin tốt cho những người yêu thích AS3, Adobe đã phát hành FlasCC hỗ trợ C ++ để chúng tôi có thể sử dụng các bộ giải tuyến tính hiện có một cách dễ dàng. :)
AturSams

4

Khi bạn có một danh sách tất cả (có thể chồng chéo) hình chữ T xảy ra trong lưới của bạn, những gì bạn còn lại là vấn đề đóng gói tối đa .

Nói chung, đây là một vấn đề NP-đầy đủ. Tuy nhiên, lưới của bạn đủ nhỏ (và thường chia thành các bài toán con độc lập thậm chí nhỏ hơn) để có thể có được các giải pháp chính xác.


Phụ lục: Đây là một thuật toán tìm kiếm quay lui cơ bản có thể thực hiện thủ thuật:

function max_packing_recursive ( set A, set S, set M ):
    if |M| < |S| then let M = S;
    for each shape X in A do:
        remove X from A;
        let B = A;
        remove all shapes that intersect with X from B;
        if |M| < |B| + |S| + 1 then:        // upper bound
            let M = max_packing_recursive( B, S + {X}, M );
        end if
        if |M| >= |A| + |S| then return M;  // shortcut
    end for
    return M;
end function

function max_packing( set A ):
    return max_packing_recursive( A, {}, {} );
end function

Dưới đây, {X, Y, Z}là tập chứa các yếu tố X, YZ(với {}là tập rỗng), và |Q|biểu thị kích thước của bộ Q.

Trong hàm đệ quy, tập hợp A chứa các hình dạng có sẵn cho giải pháp còn lại, Schứa các hình dạng trong ứng cử viên giải pháp hiện tại và Mlà giải pháp tối đa cho đến nay (mà bạn có thể muốn lưu trữ dưới dạng biến toàn cục thay vì sao lưu chuỗi cuộc gọi). Tối ưu hóa quan trọng là trên dòng được đánh dấu // upper bound, cắt tỉa các nhánh của cây tìm kiếm mà không thể trả về một giải pháp tốt hơn M.

(Trên thực tế, vì chúng ta biết rằng mỗi hình chữ T chứa chính xác bốn trang web, nên có thể đạt được giới hạn trên tốt hơn nhiều bằng cách thay thế |B| bằng số lượng các trang web riêng biệt được bao phủ bởi các hình dạng B, chia cho bốn và làm tròn xuống (và tương tự như |A|trên dòng được đánh dấu bằng // shortcut). Tuy nhiên, thuật toán như đã nêu ở trên, hoạt động cho các bộ sưu tập hình dạng tùy ý.)

Một tối ưu hóa bổ sung có thể, mà tôi đã không thực hiện ở trên, sẽ là kiểm tra ở đầu hàm đệ quy xem có Aphân chia thành nhiều tập con độc lập hay không, theo nghĩa là không có hình dạng nào trong các tập hợp con khác nhau, và nếu vậy, hãy áp dụng thuật toán cho từng tập con riêng biệt. (Trong mọi trường hợp, bạn chắc chắn sẽ muốn làm điều này ít nhất một lần ở cấp cao nhất trước khi gọi thuật toán đệ quy.) Sắp xếp các hình dạng Amột cách thích hợp trước khi lặp qua chúng, ví dụ như tăng thứ tự theo số lượng hình dạng chồng chéo, cũng có thể giúp .


Vâng, tôi nghĩ rằng anh ta có thể sử dụng ILP để giải quyết nó tương đối không gây đau đớn vì quy mô của vấn đề .. 2 ^ 20 ~ = 1.000.000 vì vậy chỉ có thể có rất nhiều hình dạng T, anh ta sẽ ổn khi sử dụng bộ giải tuyến tính cho việc này . Nó rõ ràng phức tạp theo cấp số nhân (Ít nhất là cho đến khi ai đó quản lý để chứng minh rằng p = np). Kích thước cho phép tránh heuristic trong trường hợp tương đối đơn giản này.
AturSams

Ilmari, cảm ơn bạn rất nhiều. Câu trả lời này cũng sẽ mất một vài đi để hiểu. Các bit hình dạng tùy ý cũng có thể hữu ích trong các lần lặp lại trong tương lai.
Assembler
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.