문제
동네 편의점의 주인인 동빈이는 N개의 동전을 가지고 있습니다. 이때 N개의 동전을 이용하여 만들 수 없는 양의 정수 금액 좋 최솟값을 구하는 프로그램을 작성하세요.
예를 들어, N = 5이고, 각 동전이 각각 3원, 2원, 1원, 1원, 9원짜리 (화페 단위) 동전이라고 가정합시다. 이패 동빈이가 만들 수 없는 양의 정수 금액 중 최초값은 8원입니다.
또 다른 예시로, N = 3이고, 각 동전이 각각 3원, 5원, 7원짜리 (화페 단위) 동전이라고 가정합시다. 이태 동빈이가 만들 수 없는 양의 정수 금액 충 최초값은 1원입니다.
입력 조건
- 첫째 줄에는 동전의 개수를 나타내는 양의 정수 N이 주어집니다. (1 <= N <= 1,000)
- 둘째 줄에는 각 동전의 화폐 단위를 나타내는 N개의 자연수가 주어지며, 각 자연수는 공백으로 구분합니다. 이때 각 화페 단위는 1,000,000 이하의 자연수입니다.
출력 조건
첫째 줄에 주어진 동전들로 만들 수 없는 양의 정수 금액 중 최솟값을 출력합니다.
입력 예시
5
3 2 1 1 9
출력 예시
8
<내 풀이>
어렵다.
현재 가지고 있는 코인들을 조합해서 나올 수 있는 숫자를 모두 새로운 리스트에 넣는다. 예를 들어 3 2 1 1 9가 있다고 가정하면, 우선 3 2 1 1 9를 새로운 리스트에 넣고, 이 5개의 코인 중에서 2개를 더해서 나올 수 있는 결과들 '어쩌구, 저쩌구, ...., '를 모두 새로운 리스트에 넣는다. 3개를 더해서, 4개를 더해서, 5개 모두 더해서 나올 수 있는 결과들도 모두 리스트에 넣는다. 이 리스트 안에 있는 수들은 중복이 되어 있을 것이기 때문에 set()을 사용해서 중복 수를 제거한다.
while 루프를 돌면서 이렇게 새로 만들어진 set에 존재하지 않는 가장 작은 양의 정수를 구한다.
좀 비효율적인 것 같다. 너무 계산할 것들이 많은 것 같다.
itertools 라이브러리를 찾았다. 이 라이브러리에 있는 combination을 활용해서 코드를 짰다.
from itertools import combinations as comb
coins = [3, 2, 1, 1, 9]
list2 = list(comb(coins, 2))
print(list2)
list3 = list(comb(coins, 3))
print(list3)
list4 = list(comb(coins, 4))
print(list4)
결과는 다음과 같이 2개, 3개, 4개의 원소로 구성된 튜플로 이루어진 리스트가 출력된다.
우리가 얻고 싶은 것은 튜플 각각을 더한 값이다.
그 값을 얻을 수 있게 코드를 짜줬다. 근데 이건 너무 긴 것 같다..
from itertools import combinations as comb
coins = [3, 2, 1, 1, 9]
list2 = list(comb(coins, 2))
print(list2)
# 튜플 안에 있는 원소를 더한 값을 새 리스트에 저장
new_list = []
for i in list2:
new_list.append(sum(i))
print(new_list)
결과는 얻었다. 하지만 코드를 좀 간단하게 만들고 싶다. 이건 나중에 찾아보고 일단 문제를 풀어보자.
<코드>
from itertools import combinations as comb
n = int(input())
coins = list(map(int, input().split()))
all_sum = [i for i in coins]
for i in range(2, len(coins)):
new_list = list(comb(coins, i))
# 튜플 안에 있는 원소를 더한 값을 새 리스트에 저장
for j in new_list:
all_sum.append(sum(j))
# 중복 제거 위해서 리스트를 set으로 만듦.
set(all_sum)
# 1부터 all_sum 안에 존재하는지 확인
number = 1
while True:
if number not in all_sum:
break
number += 1
print(number)
<책 풀이>
n = int(input())
data = list(map(int, input().split()))
data.sort()
target = 1
for x in data:
# 만들 수 없는 금액을 찾았을 때 반복 종료
if target < x:
break
target += x
# 만들 수 없는 금액 출력
print(target)
사실 책의 풀이가 이해되지 않는다. 책에는 그리디 알고리즘이 익숙하지 않다면 이해되지 않을 수 있는 문제라고 적혀있다. 그리디 알고리즘 문제를 더 많이 풀어봐야겠다. 나중엔 이해가 되겠지!
일단 책의 설명은 다음과 같다.
동전을 오름차순 정렬한다. 이후에 1부터 차례대로 특정한 금액을 만들 수 있는지 확인한다.
예를 들어 1, 2, 3, 8 동전이 있다고 가정하자.
- 우선 1을 만들 수 있는지 확인하기 위해 target = 1로 설정한다.
- 동전 1이 있기 때문에 target을 만들 수 있다. target = 1 + 1 = 2로 업데이트한다. (1까지 모든 금액을 만들 수 있다는 뜻)
- target = 2를 만들 수 있는지 확인한다. 동전 2가 있기 때문에 target을 만들 수 있다. target = 2 + 2 = 4로 업데이트한다. (3까지 모든 금액을 만들 수 있다는 뜻)
- target = 4를 만들 수 있는지 확인한다. 동전 3이 있기 때문에 target을 만들 수 있다. target = 4 + 3 = 7로 업데이트한다. (6까지 모든 금액을 만들 수 있다는 뜻)
- target = 7을 만들 수 있는지 확인한다. 동전 8이 있다. 따라서 7을 만들 수 있다. 정답은 7이다.
'코딩 테스트' 카테고리의 다른 글
[이코테] 그리디 문제 : Q 06. 무지의 먹방 라이브 (0) | 2023.07.19 |
---|---|
[이코테] 그리디 문제 : Q 05. 볼링공 고르기 (0) | 2023.07.19 |
[이코테] 그리디 문제 : Q 03. 문자열 뒤집기 (0) | 2023.07.11 |
[이코테] 그리디 문제 : Q 02. 곱하기 혹은 더하기 (0) | 2023.07.08 |
[이코테] 그리디 문제 : Q 01. 모험가 길드 (0) | 2023.07.08 |