CJam, 119 91 bayt
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?
Bu kesin olarak doğru, deterministik olmayan bir yaklaşım.
Masaüstümde ikinci test durumu genellikle 10 dakikadan daha kısa bir sürede bitiyor.
İlk vaka anında biter. CJam tercümanında çevrimiçi olarak deneyin .
Örnek çalışma
$ 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
Fikir
Zaman sınırları olmadan, geçerli bir kare bulana kadar rastgele kareler oluşturabiliriz. Bu yaklaşım, bu fikre dayanarak iki optimizasyon ekler:
Yerine sözde-rasgele bir yan uzunluğu kare üretilmesi N , biz yan uzunluğunun kareler oluşturmak N-1 , bir oluşturmak için bir sütun eklemek N x (N-1) satır toplamı sahip dikdörtgen S , o zaman bir sıra bir kare meydana getirmek üzere yan uzunluk N sütunları toplamı sahip S .
Tüm sütunların elemanlarının toplamı NS olacağından ve ilk N-1 satırlarının elemanlarının toplamı (N-1) S olduğundan, son satır da S toplamına sahip olacaktır .
Bununla birlikte, bu işlem geçersiz bir matris oluşturabilir, çünkü son satırın ve sütunun tüm öğelerinin benzersiz veya [A ... B] aralığında olacağının garantisi yoktur .
[A ... B] ' de benzersiz tam sayılardan oluşan bir kareyi ve rastgele sıradaki N-1 yan uzunluğu seçmek çok uzun sürecektir. Bir şekilde , önceki madde işaretinde detaylandırılmış olan işlemi uyguladıktan sonra geçerli bir N yan kare uzunluğu ile sonuçlanma şansı yüksek olan karelere öncelik vermeliyiz .
Her satırın ve sütunun toplam S toplamına sahip olması gerektiği düşünüldüğünde , elemanlarının ortalama S / N değeri vardır . Bu nedenle, bu ortalamaya yakın daha fazla eleman seçmek şansımızı arttırmalıdır.
[A ... B] ' deki her I için , rastgele 0 ile (I - S / N) 2 + 1 arasında bir kayan nokta seçer ve [A ... B] öğelerini toplanan kayan noktalara göre sıralarız. İlk N 2 sayılarını tutarız ve bunları kare şeklinde okuma sırasına yerleştiririz.
Her adımda 0 ile (I - S / N) 2 + 1 arasındaki tüm gerçek sayıların mükemmel bir şekilde dağılmış olduğu varsayıldığında , tüm karelerin sıfıra düşme olasılığı yoktur, bu da işlemin sonunda biteceği anlamına gelir.
kod
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.