Tạo hiệu quả tất cả các phân vùng vector


12

Một phân vùng vectơ đang phân tách một vectơ lên ​​một loạt các vectơ sao cho tổng của chúng là bản gốc. Dưới đây là một vài phân vùng:

[3, 1, 2] = [3, 1, 2]
[3, 1, 2] = [0, 0, 1] + [0, 0, 1] + [0, 1, 0] + [1, 0, 0] + [2, 0, 0]
[3, 1, 2] = [1, 1, 2] + [2, 0, 0]

Ở đây bổ sung vector được thực hiện phần tử khôn ngoan. Phân vùng hợp lệ không chứa bất kỳ vectơ nào có số nguyên âm hoặc vectơ hoàn toàn bằng không.

Bây giờ thách thức là viết một chương trình hoặc hàm tạo ra tất cả các phân vùng vectơ có thể có cho một vectơ đích. Điều này nghe có vẻ tương đối dễ dàng ...

... nhưng có một thay đổi. Nếu vectơ đầu vào có kích thước L và phân vùng lớn nhất mà nó tạo ra có các phần tử M, bạn không được sử dụng nhiều hơn bộ nhớ O (L * M).

Bạn có thể giả sử rằng một số nguyên sử dụng bộ nhớ O (1). Điều này có nghĩa là bạn phải xuất các phân vùng khi bạn tạo chúng.Trên hết, bạn chỉ phải xuất mỗi phân vùng chính xác một lần. Ví dụ: đây là cùng một phân vùng:

[3, 1, 2] = [3, 0, 2] + [0, 1, 0]
[3, 1, 2] = [0, 1, 0] + [3, 0, 2]

Nếu bạn đã xuất cả câu trả lời của bạn là không hợp lệ.


Tất cả các phân vùng cho [3, 2] :

[3, 2]
[0, 1] + [3, 1]
[0, 1] + [0, 1] + [3, 0]
[0, 1] + [0, 1] + [1, 0] + [2, 0]
[0, 1] + [0, 1] + [1, 0] + [1, 0] + [1, 0]
[0, 1] + [1, 0] + [2, 1]
[0, 1] + [1, 0] + [1, 0] + [1, 1]
[0, 1] + [1, 1] + [2, 0]
[0, 2] + [3, 0]
[0, 2] + [1, 0] + [2, 0]
[0, 2] + [1, 0] + [1, 0] + [1, 0]
[1, 0] + [2, 2]
[1, 0] + [1, 0] + [1, 2]
[1, 0] + [1, 1] + [1, 1]
[1, 1] + [2, 1]
[1, 2] + [2, 0]

Để kiểm tra câu trả lời của bạn, hãy chạy nó trên [3, 2, 5, 2] . Nó sẽ tạo ra 17939 phân vùng, tất cả đều tổng hợp [3, 2, 5, 2]và tất cả đều là duy nhất (bạn có thể kiểm tra tính duy nhất bằng cách sắp xếp trước tiên từng phân vùng theo từ vựng).


Mã ngắn nhất trong byte thắng.

Câu trả lời:


3

Python 2, 289 byte

Thuật toán vũ phu đơn giản. Xử lý toàn bộ danh sách dưới dạng một số trong cơ sở max(input)+1( b) và kiểm tra từng "số" trong phạm vi [0, b**(L*M))để xem nếu nó:

  1. Tổng số tiền đúng
  2. Theo thứ tự bảng chữ cái (đảm bảo tính duy nhất)

Nếu danh sách phù hợp với các tiêu chí này, chương trình sẽ đưa ra nó với tất cả các vectơ hoàn toàn bằng không.

Sử dụng bộ nhớ

Cấu trúc dữ liệu lớn nhất tôi sử dụng trong chương trình này là một danh sách gấp đôi, một chiều dài danh sách Mchứa độ dài liss Lđể cung cấp O(L*M)bộ nhớ.

Đối với các cấu trúc dữ liệu khác của tôi, tôi có 3 int toàn cầu O(3), 1 chiều dài danh sách L( O(L)), 1 chiều dài mảng M( O(M)) và một bản sao của mảng lớn nhất khi xuất ra (O(L*M) ).

Tổng cộng, điều này mang lại cho tôi cách sử dụng bộ nhớ O(2*L*M + L + M + 3)để đơn giản hóa O(L*M), hoàn thành các tiêu chí.

Thời gian phức tạp

Là một thuật toán vũ phu, thuật toán này cực kỳ chậm. Đối với vòng lặp while để thoát, int cuối cùng trong mảng cần phải có b-1. Vòng lặp cần phải chạy b**(L*M)lần trước khi điều đó xảy ra.

Ngoài ra, mỗi khi danh sách chạy, nó cần kiểm tra cả hai điều kiện và in danh sách trong trường hợp xấu nhất, sử dụng các L*M+L+Mlần lặp. Điều này đơn giản hóa để cung cấp cho một tổng thể O(L*M * b**(L*M)). Tôi đã thử kiểm tra chương trình của mình [3, 2, 5, 2], nhưng đã bỏ cuộc sau 45 phút.

Chương trình chơi gôn

v=input()
L=len(v)
M=sum(v)
b=max(v)
R=range
t=[L*[0]for i in R(M)]
def A(l,i):
 if i<L*M-1and~-b<l[i/L][i%L]:A(l,i+1)
 l[i/L][i%L]=-~l[i/L][i%L]%-~b
while t[-1][-1]<b:
 if v==[sum(q[i]for q in t)for i in R(L)]and all(`t[i]`>=`t[i+1]`for i in R(M-1)):print[x for x in t if[0]*L!=x]
 A(t,0)

Tôi có thể chơi golf nhiều hơn một chút, đặc biệt là phần tăng dần. Mã sắp tới.


Chắc chắn không phải là hiệu quả mà tôi đã hy vọng khi tôi đăng câu hỏi này, nhưng tôi đoán nó về mặt kỹ thuật giải quyết vấn đề :)
orlp
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.