morijwana
수로그
morijwana
전체 방문자
오늘
어제
  • 분류 전체보기
    • 강의노트
    • Machine Learning
      • Pandas
      • NLP
    • Computer Science
      • Linux
      • TIL
    • Development
      • React
      • Swift
      • Javascript
    • 스터디 기록
      • Clean Code
      • 구글 BERT의 정석
      • 개발도서
      • 기타
    • Problem Solving
      • Baekjoon
      • ICPC Sinchon
    • 끄적
      • 끄적끄적
      • 요리왕

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 구부정스터디
  • 프레임워크없는프론트엔드개발
  • ML
  • word2vec
  • 구글BERT의정석
  • 자연어처리
  • nlp
  • 회고
  • Solution Challenge
  • cs224n
  • 백준
  • Bert
  • gdsc
  • 데이터사이언스
  • Python
  • GDSC Sookmyung
  • 프로그래밍언어론
  • 민트하임스터디
  • Pandas
  • 개발도서

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
morijwana

수로그

Problem Solving/ICPC Sinchon

백준 1248번 - 맞춰봐(Python)

2020. 7. 22. 23:19

초급 스터디 - 02 Backtracking 예제

* 강의를 들으며 배운 것을 정리하는 포스팅입니다. 제가 생각해낸 아이디어가 아닙니다. *

문제

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

 

1248번: 맞춰봐

문제 규현이는 멍청하다. 왜냐하면, 1~10까지 수 밖에 모르기 때문이다. 어느 날 규현이 옆을 지나가던 태석이가 규현이를 보고 이렇게 외쳤다. "빵빵!!" 규현이는 "아하!" 하면서 세상에는 빵이란

www.acmicpc.net

풀이

입력으로 주어진 조건을 n x n 배열에 저장한 다음 각 조건을 검사하는 방법은 1)행 단위, 2)열 단위의 두 가지 방법이 있다.

1)
행 단위로 검사를 하는 경우는 n = 4일 때 0부터 0까지의 합, 0부터 1까지의 합, 0부터 3까지의 합... 2부터 2까지의 합, 2부터 3까지의 합... 3부터 3까지의 합 순서로 보는 것이다. 이 경우는 백트래킹을 할 때 어느 레벨까지 백트래킹을 해야 할 지 감이 잘 안 잡힌다.

2)
열 단위로 검사를 하는 경우는 다시 위에서 아래로 검사하는 경우(0부터 n-1까지)와 아래에서 위로 검사하는 경우(n-1부터 0까지)의 2가지 경우로 나뉜다. 강사님께서는 아래에서 위로 검사하는 경우를 선택하셨는데, 그 이유는 아래에서 위로 검사를 하게 되면 각 열마다 처음 실시하는 검사는 무조건 x에서 x까지의 합이므로 x번째 수의 부호를 바로 알 수 있기 때문이다. 열 단위 검사를 했을 때의 장점은 수열의 i번째 수를 확실하게 정할 수 있으므로 이전 단계의 숫자를 다시 고르기 위해 돌아갈 필요가 없다는 것이다.

check(index)
현재 index 번째 수를 채울 때 sign[i][index]의 부호조건을 만족하는지 아닌지 검사하는 함수다. index부터 1씩 감소하며 0까지의 조건을 만족하는지 확인한다. 즉 i부터 i번째까지의 합, i-1부터 i번째까지의 합, ... 0부터 i번째까지의 합 순서로 확인한다. 위에서 우리가 열 단위/아래에서 위로 검사하는 방법을 채택했기 때문이다.
조건을 하나라도 만족하지 않으면 False, 전부 다 만족하는 경우 True를 리턴한다.

solve(index)

  • Base case
    index == n인 경우. check(index)를 만족해야 solve(index + 1)을 호출할 수 있으므로 Index == n이면 모든 부호 조건을 만족한 것이다.
  • Recursive case
    1. 현재 index가 n 미만이고, sign[index][index]의 부호 조건이 0인 경우 => index ~ index번째 수의 합이 0이 되려면 index번째 수는 무조건 0이 되어야 하므로 예외처리
    2. 그 외의 경우 => i의 값이 1부터 10까지 증가하는 반복문 안에서 i에다가 부호를 붙여준 후(sign[index][index] 참고) check()로 테스트, 만족하는 경우 solve(i + 1) 재귀 호출하여 다음 단계 진행

코드

# 백트래킹
# 가능한 모든 경우의 수의 최대값이 16조 이상이므로 완전 탐색으로는 제한 시간(2초)안에 구현 불가
# 필요한 정보, Base Case, Recursive Case 생각하기


def check(index):  # 현재 index 번째 수를 채울 때 sign[i][index]의 부호조건을 만족하는지 아닌지 검사하는 함수(역순)
    s = 0
    for i in range(index, -1, -1):
        s += ans[i]
        if sign[i][index] == 0:
            if s != 0:
                return False
        elif sign[i][index] < 0:
            if s >= 0:
                return False
        elif sign[i][index] > 0:
            if s <= 0:
                return False
    return True


def solve(index):   # 현재 index 번째 수를 채우는 함수
    if index == n:  # check(index)를 만족해야 solve(index + 1)의 재귀호출이 가능하므로 index = n이면 sign 배열의 모든 부호 조건을 만족한 경우이므로 True 리턴
        return True
    if sign[index][index] == 0:  # recursive case 1: 현재 index 수가 n 미만이고 0이면 바로 조건 검사 후 재귀 호출
        ans[index] = 0           # index ~ index 번째의 수의 합이 0이 되려면 ans[index]가 0이 되어야 함!
        return check(index) and solve(index + 1)

    for i in range(1, 11):       # recursive case 2: 현재 index 수가 n 미만이고 0이 아니면 index 번째 부호를 붙인 후 조건 검사 후 재귀 호출
        ans[index] = i * sign[index][index]
        if check(index) and solve(index + 1):
            return True
    return False


n = int(input())
ans = [0] * n  # 정답이 저장될 리스트
signs = list(input())  # 부호 조건이 저장될 리스트
sign = [[0 for _ in range(n)] for _ in range(n)]

idx = 0
# +, - 대신 1, -1을 저장해 solve()에서 해당 인덱스의 수에 부호를 쉽게 붙일 수 있도록 함
for i in range(0, n):
    for j in range(i, n):
        if signs[idx] == '+':
            sign[i][j] = 1
        elif signs[idx] == '-':
            sign[i][j] = -1
        idx += 1

solve(0)
print(' '.join(map(str, ans)))
저작자표시 (새창열림)

'Problem Solving > ICPC Sinchon' 카테고리의 다른 글

백준 11582번 - 치킨 TOP N(C++)  (1) 2020.07.29
백준 10825번 - 국영수(C++, Python - lambda)  (0) 2020.07.29
백준 15811번 - 복면산!?(Python)  (0) 2020.07.19
    'Problem Solving/ICPC Sinchon' 카테고리의 다른 글
    • 백준 11582번 - 치킨 TOP N(C++)
    • 백준 10825번 - 국영수(C++, Python - lambda)
    • 백준 15811번 - 복면산!?(Python)
    morijwana
    morijwana
    행복한 휴학생의 devlog

    티스토리툴바