CJam, 119 91 바이트
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?
이것은 아마도 정확하고 비 결정적 접근 방식입니다.
내 데스크탑에서 두 번째 테스트 사례는 일반적으로 10 분 이내에 완료됩니다.
첫 번째 경우는 즉시 완료됩니다. CJam 통역사 에서 온라인으로 사용해보십시오 .
샘플 런
$ 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
생각
시간 제한이 없으면 유효한 사각형을 찾을 때까지 무작위로 사각형을 생성 할 수 있습니다. 이 접근법은 두 가지 최적화를 추가하여이 아이디어를 기반으로합니다.
측면 길이 N 의 의사 난수 생성 제곱 대신 측면 길이 N-1의 제곱을 생성 하고 행 하나에 합이 S 인 N × (N-1) 사각형 을 형성하기 위해 하나의 열을 추가 한 다음 하나의 행을 제곱을 형성합니다. 측면 길이 N 그 열의 합이 S를 .
모든 열의 요소 합이 NS 이고 첫 번째 N-1 행 의 요소 합 이 (N-1) S 이므로 마지막 행에도 합 S가 있습니다.
그러나 마지막 행과 열의 모든 요소가 고유하거나 [A ... B] 범위에 속한다고 보장 할 수 없으므로이 프로세스는 잘못된 행렬을 생성 할 수 있습니다 .
[A ... B] 에서 고유 한 정수의 제곱 과 측면 길이 N-1 을 무작위로 균일하게 선택하면 너무 오래 걸립니다. 우리는 어떻게 든 이전 글 머리표에 자세히 설명 된 프로세스를 적용한 후 측면 길이 N 의 유효한 제곱이 될 가능성이 높은 제곱의 우선 순위를 정해야 합니다.
각 행과 열의 합이 S 의 값을 가져야하는 경우 해당 요소의 평균은 S / N 입니다. 따라서 해당 평균에 가까운 요소를 더 많이 선택하면 기회가 증가합니다.
[A ... B]의 각 I 에 대해 , 우리는 0 과 (I-S / N) 2 + 1 사이에서 실수를 의사 랜덤하게 선택하고 [A ... B] 의 요소를 선택된 부동 소수점으로 정렬합니다 . 우리는 첫 번째 N 2 숫자를 유지하고 정사각형으로 읽는 순서대로 놓습니다.
각 단계에서 0 과 (I-S / N) 2 + 1 사이의 모든 실수의 완벽하게 균일 한 분포를 가정하면 , 모든 제곱은 선택 될 확률이 0이 아니므로 프로세스가 결국 완료됩니다.
암호
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.