Notice

[Python] 백준 14888번 연산자 끼워넣기

 

 


풀이

# 연산자는 앞에서부터
# 나눗셈은 정수 나눗셈으로 몫만 취함
# 음수를 양수로 나눌 때, 양수로 바꾼뒤 몫을 구하고 음수로 변환
from itertools import permutations

N = int(input())
num = list(map(int, input().split()))
sign_list = list(map(int, input().split()))
sign = ['+', '-', '*', '/']

op = []

for i in range(len(sign_list)):
    for j in range(sign_list[i]):
        op.append(sign[i])


result = []
for i in permutations(op, N-1):
    calc = num[0]
    for j in range(1, N):
        if i[j-1] == '+':
            calc += num[j]
        elif i[j-1] == '*':
            calc *= num[j]
        elif i[j-1] == '/':
            calc = int(calc/num[j])
        elif i[j-1] == '-':
            calc -= num[j]

    result.append(calc)

print(max(result))
print(min(result))

순열을 이용해 연산자를 정렬해서 풀이하였다. 그런데, 순열은 시간복잡도가 O(n!)으로 너무 커서 Pypy3에서만 통과했다.

 

 

 

다른 풀이 이해

백트래킹을 이용한 풀이

n = int(input())
number = list(map(int, input().split()))
add, sub, mul, div = map(int, input().split())

max_result = - int(1e9)
min_result = int(1e9)

def dfs(add, sub, mul, div, sum, idx):
    global max_result, min_result
    if idx == n:
        max_result = max(max_result, sum)
        min_result = min(min_result, sum)
        return
        
    if add:
        dfs(add-1, sub, mul, div, sum + number[idx], idx + 1)
    if sub:
        dfs(add, sub-1, mul, div, sum - number[idx], idx + 1)
    if mul:
        dfs(add, sub, mul-1, div, sum * number[idx], idx + 1)
    if div:
        dfs(add, sub, mul, div-1, int(sum / number[idx]), idx + 1)
        
dfs(add, sub, mul, div, number[0], 1)
print(max_result)
print(min_result)

 

연산자 우선순위가 반영되지 않고 순서되고 연산되기 때문에 백트래킹을 사용할 수 있다.

 


백트래킹

왔던 길을 되돌아 가며 가지치기하는 방식으로 탐색하기 때문에 완전 탐색에 비해 수행 시간이 적게 걸린다.

ex) 미로찾기, n-Queen 문제, Map coloring, 부분집합의 합 문제 등에서 활용

 

  • Promising : 트리 구조를 기반으로 DFS로 깊이 탐색을 진행하면서 각 루트에 대해 조건에 부합하는지 체크한다.
  • Pruning : 해당 트리에서 조건에 맞지않는 노드는 더 이상 DFS로 깊이 탐색을 진행하지 않고 가지치기를 한다.

즉, 재귀를 이용한 완전 검색을 한 후, 가지치기를 추가하는 기법

 

 

1) 완전 검색

#부분집합 기본코드
def printSet(n):
    for i in range(n):
        if A[i] == 1:
            print(data[i], end = " ")
    print()
    
def powerset(k, n):            # k는 A배열의 k인덱스의 포함 유무를 판별한다.
    if n == k:
        printSet(k)
    else:
        A[k] = 1
        powerset(k+1, n)       # 배열 A에 체크하고 다음 인덱스로 넘어간다
        A[k] = 0               # 재귀로 되돌아와서 체크 했던걸 다시 원상복귀시킨다
        powerset(k+1, n)

data = 구하려는 리스트
n = len(data)                  # 부분집합을 구하는 리스트의 수
A = [0]* n                     # 포함 유무를 체크할 리스트 (0이 미포함, 1이 포함)

 

 

2) 가지치기

# 부분집합의 합
def powerset(k, n, sum):
    if sum > 10:          # 부분집합의 합을 구하는 문제에서 구하고자하는 값인 10을 넘는다면 더이상 계산할 필요가 없으므로 return해버린다.(가지치기)
        return
    if n == k:
        printSet(k, sum)
    else:
        A[k] = 1
        powerset(k+1, n, sum+data[k])       
        A[k] = 0               
        powerset(k+1, n, sum)

 

 

 

 

 

 

[python] 백트래킹(backtracking)

0. 들어가면서 일단, 개념위주가 아니라 실전 문제 푸는 스킬위주로 적을예정이다. 그리고 백트래킹에 대해 가능한 모든 내용을 담을 예정이다. 즉, 계속 업데이트가 될 것이며, 쭉 이해만 하면

han-py.tistory.com

 

 

예제) n과 m(1)

 

[Python] 백트래킹 (+ DFS와 차이)

백트래킹이란? 백트래킹이란 현재 상태에서 가능한 모든 경로를 따라 들어가 탐색하다, 원하는 값과 불일치하는 부분이 발생하면 더 이상 탐색을 진행하지 않고 전 단계로 돌아가는, 즉 이름 그

veggie-garden.tistory.com

 

 

[백준BOJ] 단계별로 문제풀기 - 백트래킹 정답 및 후기(파이썬, python)

백준 알고리즘에서 제공되는 문제들 중 단계별로 문제 풀기 - 백트래킹을 파이썬으로 풀어보았다. 코드는 8문제 통째로 깃허브에 올려놓았으며 각 문제마다 주석으로 표시해놨다. www.acmicpc.net/st

moz1e.tistory.com

 

 

 

 

 

 

https://www.acmicpc.net/problem/14888

 

14888번: 연산자 끼워넣기

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 

www.acmicpc.net

 

'알고리즘' 카테고리의 다른 글

[Python] 백준 11047번 동전 0  (0) 2022.12.02
[이코테] 3장 그리디  (0) 2022.12.02
[Python] 백준 2581번 소수  (0) 2022.11.30
[Python] 백준 1292번 쉽게 푸는 문제  (0) 2022.11.30
[Python] 백준 1978번 소수 찾기  (0) 2022.11.30
글쓰기 설정