////
Search

연산자 끼워넣기

소스코드

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를 출력하면 끝!

회고

브루트포스를 쓰려고 하면 본능적으로 거부감이 듭니다. 아마 경우의 수가 많이 커지는 게 본능적으로 회피하게 되는 것 같습니다. 그러나 항상 주어진 값의 크기를 보고 판단해야하는데, 자꾸 직관에 제 문제풀이 방식을 의존하는 경향이 강하다는 생각이 듭니다. 이것 또한 여러 문제를 풀면서 브루트포스인 경우의 허용 크기에 대해 감을 잡아가야할 것 같습니다.
특강에서 배운 재귀에서의 ‘마법의 요정’이 생각보다 제게 도움이 많이 되고 있습니다. 정말 좋네요. 마법의 요정!