Notion에서 작성한 글이라, 여기에서 더 깔끔하게 보실 수 있습니다! 😮😊
[2, 4, 1, 3, 0]
에 대해 생각해 보자.[0]
)의 값인 는 그 다음 인덱스를 의미한다.[2]
의 값인 은 그 다음 인덱스를 의미한다.[1]
의 값인 는 그 다음 인덱스를 의미한다[4]
의 값인 은 그 다음 인덱스인데, 이는 시작 인덱스([0]
)과 동일하므로 이렇게 네 원소가 하나의 사이클 그룹을 이룸을 알 수 있다.[3]
)에 대해서도 같은 방식으로 생각해 주면, [3]
의 값인 은 자기 자신을 가리키므로 이 또한 길이가 1인 사이클임을 알 수 있다.import sys
input = sys.stdin.readline
from itertools import permutations
def convert(c):
if c.isalpha(): return -(ord(c)-64)
return int(c)
def score(cycle):
used = set()
sign = -1
ret = 1
for i in range(n):
if i not in used:
sign *= -1
j = i
while j not in used:
used.add(j)
ret *= board[j][cycle[j]]
j = cycle[j]
return sign*ret
n = int(input())
board = [[*map(convert, input().rstrip())] for _ in range(n)]
mx, mn = -1000000, 1000000
for cycle in permutations(range(n)):
cur = score(cycle)
mx = max(mx, cur)
mn = min(mn, cur)
print(mn, mx, sep='\n')
'A'
부터 'I'
까지의 문자가 의미하는 것은 부터 이므로, 입력받은 문자가 알파벳이라면 -(ord(c)-64)
로, 그렇지 않다면(부터 까지의 수라는 것이므로) 정수로 변환하는 함수를 만들었다.float('inf')
도 있지만 나이브하게 으로 잡았다.score()
함수는 만들어진 사이클에 대해 각 도미노에 쓰여 있는 수를 곱해나가 점수를 계산하는 함수이다.sign
의 역할은 return할 점수의 부호이다. 사이클 그룹의 개수를 누적시킨다음 1 if cnt%2 else -1
을 이용하는 방법도 있겠으나, 부호만 바뀐다는 점에 착안하여 조금 더 직관적이진 않을까 싶어 위와 같이 짰다. 지금 생각해보니 두 방법 모두 일장일단이 있는 것 같다.def permutations(n):
ret = []
used = set()
def _perm(p=[]):
if len(p) == n: ret.append(p[:]); return
for i in range(n):
if i not in used:
p.append(i)
used.add(i)
_perm(p)
used.discard(i)
p.pop()
_perm()
return ret
itertools.permutations(range(n))
과 같은 역할을 하는 코드를 직접 구현했었다.itertools
가 워낙 빠르므로… 공부할 겸 처음 제출할 땐 직접 permutations
를 짰고, AC 받은 뒤엔 itertools
로 다시 제출했다.References