1학년
문제
상근이가 1학년 때, 덧셈, 뺄셈을 매우 좋아했다. 상근이는 숫자가 줄 지어있는 것을 보기만 하면, 마지막 두 숫자 사이에 '='을 넣고, 나머지 숫자 사이에는 '+' 또는 '-'를 넣어 등식을 만들며 놀고 있다. 예를 들어, "8 3 2 4 8 7 2 4 0 8 8"에서 등식 "8+3-2-4+8-7-2-4-0+8=8"을 만들 수 있다.
상근이는 올바른 등식을 만들려고 한다. 상근이는 아직 학교에서 음수를 배우지 않았고, 20을 넘는 수는 모른다. 따라서, 왼쪽부터 계산할 때, 중간에 나오는 수가 모두 0 이상 20 이하이어야 한다. 예를 들어, "8+3+2-4-8-7+2+4+0+8=8"은 올바른 등식이지만, 8+3+2-4-8-7이 음수이기 때문에, 상근이가 만들 수 없는 등식이다.
숫자가 주어졌을 때, 상근이가 만들 수 있는 올바른 등식의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 숫자의 개수 N이 주어진다. (3 ≤ N ≤ 100) 둘째 줄에는 0 이상 9 이하의 정수 N개가 공백으로 구분해 주어진다.
출력
첫째 줄에 상근이가 만들 수 있는 올바른 등식의 개수를 출력한다. 이 값은 263-1 이하이다.
처음에는 어떻게 풀지 막막하였다.
수의 숫자가 너무 컸기 때문에 브루트포스느, 백트레킹으로는 감당할 수 없는 정도의 크기였다.
그래서보니 DP 문제였고 DP로 어떻게 풀지 생각해보았다.
역시나 처음에는 잘 떠오르지 않았다.
그러다 생각난 것이 각 연산 후에 나 올 수 있는 숫자의 갯수를 세리는 것이였다.
그래서 DP의 크기를 (N-1)*21의 크기로 N-1개의 숫자를 연산하고 숫자의 범위가 0~20까지였기 때문에
이렇게 설명하고 계산을 하였다.
import sys
input = sys.stdin.readline
N = int(input())
nums = list(map(int,input().split()))
# 구해야하는 숫자
end = nums[-1]
# 총 (N-1)개의 숫자를 연산하고 0~20까지 숫자이기 때문에
dp = [[0] * 21 for _ in range(N-1)]
# 처음 숫자는 1개있기 때문에
dp[0][nums[0]] = 1
# 각 숫자를 돌아다니기
for i in range(1,N-1):
# 전의 연산에서 나온 숫자 찾기
for j in range(21):
# 0이면 그 숫자가 나올 수 없는 것이기 때문에
if dp[i-1][j] == 0:
continue
# 그전의 숫자 j와 현재 숫자를 더해서 범위 파악
if 0 <= j + nums[i] <= 20:
# 범위 안이라면 지금 구한 숫자가 나올 수 있는 경우에서
# 현재 숫자에서 나올 수 있는 경우의 수를 더한다.
dp[i][j + nums[i]] += dp[i-1][j]
# 빼기
if 0 <= j - nums[i] <= 20:
dp[i][j - nums[i]] += dp[i-1][j]
# 마지막에 총 연산에서 나올 수 있는 숫자의 등식의 갯수를 알 수 있다.
# 그래서 우리가 원하는 숫자인 end가 나올 수 있는 등식뽑아내기
print(dp[-1][end])
'@@@ 알고리즘 > 백준 스터디' 카테고리의 다른 글
1241(머리 톡톡) - 해결 (0) | 2021.12.13 |
---|---|
7490(0 만들기) - 해결 (0) | 2021.12.13 |
19598(최소 회의실 개수) - 참고 (0) | 2021.12.08 |
1041(주사위) - 해결(참고) (0) | 2021.12.07 |
20311(화학 실험) - 해결 (0) | 2021.12.06 |