CJam, 119 91 byte
q~:M;),>:R;(:L{{R{ML)d/-Y#)mr}$L/L<2{{M1$:+-+}%z}*:U:+__O|=R*-}gU{:s_:,:e>f{Se[}}%zSf*N*}M?
Đây là một cách tiếp cận có thể chứng minh chính xác, không xác định.
Trên máy tính để bàn của tôi, trường hợp thử nghiệm thứ hai thường kết thúc sau chưa đầy 10 phút.
Trường hợp đầu tiên kết thúc ngay lập tức. Hãy thử trực tuyến trong trình thông dịch CJam .
Chạy mẫu
$ cjam grid.cjam <<< '8 1 300 500'
77 66 37 47 56 46 86 85
63 102 70 72 49 54 81 9
62 69 58 57 71 17 48 118
64 65 67 87 53 44 80 40
73 60 55 89 51 76 84 12
68 59 28 78 74 38 50 105
61 75 52 43 125 83 42 19
32 4 133 27 21 142 29 112
Ý kiến
Không có giới hạn thời gian, chúng ta chỉ có thể tạo ngẫu nhiên các hình vuông cho đến khi tìm thấy một hình vuông hợp lệ. Cách tiếp cận này dựa trên ý tưởng đó, thêm hai tối ưu hóa:
Thay vì giả ngẫu nhiên tạo ra hình vuông có độ dài cạnh N , chúng tôi tạo ra các hình vuông có độ dài cạnh N-1 , thêm một cột để tạo thành hình chữ nhật N × (N-1) có các hàng có tổng S , sau đó một hàng để tạo thành một hình vuông bên chiều dài N có các cột có tổng S .
Kể từ khi tổng các yếu tố của tất cả các cột sẽ NS và tổng các yếu tố của người đầu tiên N-1 dòng là (N-1) S , hàng cuối cùng cũng sẽ có tổng S .
Tuy nhiên, quá trình này có thể tạo ra một ma trận không hợp lệ, vì không có gì đảm bảo rằng tất cả các yếu tố của hàng và cột cuối cùng sẽ là duy nhất hoặc nằm trong phạm vi [A ... B] .
Chọn một hình vuông các số nguyên duy nhất trong [A ... B] và độ dài cạnh N-1 đồng nhất ngẫu nhiên sẽ mất quá nhiều thời gian. Chúng tôi bằng cách nào đó phải ưu tiên các hình vuông có cơ hội cao hơn dẫn đến một hình vuông có độ dài cạnh N hợp lệ sau khi áp dụng quy trình chi tiết trong điểm đạn trước đó.
Cho rằng mỗi hàng và cột phải có một khoản S , các yếu tố của nó có trung bình S / N . Do đó, chọn nhiều yếu tố gần với mức trung bình đó sẽ tăng cơ hội của chúng tôi.
Đối với mỗi I trong [A ... B] , chúng tôi giả ngẫu nhiên chọn một số float giữa 0 và (I - S / N) 2 + 1 và sắp xếp các phần tử của [A ... B] theo các số float được chọn. Chúng tôi giữ các số N 2 đầu tiên và đặt chúng theo thứ tự đọc trong một hình vuông.
Giả sử phân phối đồng đều hoàn toàn tất cả các số thực từ 0 đến (I - S / N) 2 + 1 trong mỗi bước, tất cả các ô vuông đều có xác suất được chọn bằng không, nghĩa là quá trình sẽ kết thúc.
Mã
q~ e# Read all input from STDIN and evaluate it.
:M; e# Save "S" in M and discard it from the stack.
),>:R; e# Transform "A B" into [A ... B], save in R and discard.
(:L e# Save "N - 1" in L and keep it on the stack.
{ e# If L is non-zero:
{ e# Do:
R{ e# For each I in R:
ML)d/ e# Compute M/Double(L+1).
-Y# e# Subtract the result from I and square the difference.
)mr e# Add 1 and pick a non-negative Double below the result.
}$ e# Sort the values of I according to the picks.
L/ e# Split the shuffled R into chunks of length L.
L< e# Keep only the first L chunks.
2{ e# Do twice:
{ e# For each row of the L x L array.
M1$ e# Push M and a copy of the row.
:+- e# Add the integers of the row and subtract their sum from M.
+ e# Append the difference to the row.
}% e#
z e# Transpose rows and columns.
}* e#
:U:+ e# Save the result in U and concatenate its rows.
__O| e# Push two copies. Deduplicate the second copy.
=R* e# Push R if all elements are unique, an empty array otherwise.
- e# Remove the result's elements from U's elements.
}g e# If the resulting array is non-empty, repeat the loop.
U{ e# For each row in U:
:s e# Convert its integers into strings.
_:, e# Copy and replace each string with its length.
:e> e# Compute the maximum length.
f{ e# For each integer, push the maximum length; then
Se[ e# Left-pad the integer with spaces to that length.
} e#
}% e#
z e# Transpose rows with columns.
Sf*N* e# Join columns by spaces, rows by linefeeds.
}M? e# Else, push M.