소스코드
import sys
input = sys.stdin.readline
N = int(input().strip())
A = list(map(int, input().strip().split()))
counts = list(map(int, input().strip().split())) # 덧셈, 뺄셈, 곱셈, 나눗셈 개수
max_result = -(float('inf'))
min_result = float('inf')
def dfs(depth, acc, plus, minus, multiply, divide):
global max_result
global min_result
if depth == N:
max_result = max(max_result, acc)
min_result = min(min_result, acc)
return
if plus > 0:
dfs(depth + 1, acc + A[depth], plus - 1, minus, multiply, divide)
if minus > 0:
dfs(depth + 1, acc - A[depth], plus, minus - 1, multiply, divide)
if multiply > 0:
dfs(depth + 1, acc * A[depth], plus, minus, multiply - 1, divide)
if divide > 0:
if acc >= 0:
dfs(depth + 1, acc // A[depth], plus, minus, multiply, divide - 1)
else:
dfs(depth + 1, -(-acc // A[depth]), plus, minus, multiply, divide - 1)
dfs(1, A[0], counts[0], counts[1], counts[2], counts[3])
print(max_result)
print(min_result)
Python
복사
풀이
•
N의 수가 매우 작습니다. 피연산자와 연산자 개수가 N, N-1이라서 트리 문제인가?를 떠올렸습니다. 그 가운데 재귀함수가 생각나서 DFS 함수를 구현했습니다.
◦
재귀함수를 작성하려니 브루트포스 문제처럼 풀어야겠더라구요. 가능한 모든 경우들을 재귀함수를 이용해서 작성했습니다.
▪
AI에게 물어보니, 최대 10개의 연산자 개수가 있는데 단순히 10팩토리얼로 생각해봐도 360만 횟수 정도의 연산횟수라서 문제가 없고 중복이 있는 연산자들에 대해서는 경우의 수가 더 적어지므로 문제가 없다고 했습니다.
◦
재귀함수의 인자 중 연산자들 개수 인자말고는 2개의 인자를 이용했습니다
▪
depth : 종료 조건을 위한 인자입니다. 재귀 호출할 때마다 1씩 증가하며 N에 도달하면 비교 연산을 수행하고 리턴합니다.
▪
acc : 해당 연산자에 대해 값을 누적해 다음 함수에게 전달합니다. 이를 이용해서 depth가 N에 도달한 함수에서 acc로 비교 연산합니다.
•
이미 초기값으로 A[0]을 사용하니 depth를 1로 시작하고 N에 도달하면 종료합니다.
•
함수를 실행하고 max_result, min_result를 출력하면 끝!
회고
•
브루트포스를 쓰려고 하면 본능적으로 거부감이 듭니다. 아마 경우의 수가 많이 커지는 게 본능적으로 회피하게 되는 것 같습니다. 그러나 항상 주어진 값의 크기를 보고 판단해야하는데, 자꾸 직관에 제 문제풀이 방식을 의존하는 경향이 강하다는 생각이 듭니다. 이것 또한 여러 문제를 풀면서 브루트포스인 경우의 허용 크기에 대해 감을 잡아가야할 것 같습니다.
◦
특강에서 배운 재귀에서의 ‘마법의 요정’이 생각보다 제게 도움이 많이 되고 있습니다. 정말 좋네요. 마법의 요정!
