[알고리즘] 바둑이 승차(DFS)
(문제) 바둑이 승차(DFS)
철수는 그의 바둑이들을 데리고 시장에 가려고 한다.
그런데 그의 트럭은 C킬로그램 넘게 태울수가 없다.
철수는 C를 넘지 않으면서 그의 바둑이들을 가장 무겁게 태우고 싶다.
N마리의 바둑이와 각 바둑이의 무게 W가 주어지면, 철수가 트럭에 태울 수 있는 가장 무거운 무게를 구하는 프로그램을 작성하세요.
입력설명
첫 번째 줄에 자연수 C(1<=C<=100,000,000)와 N(1<=N<=30)이 주어집니다.
둘째 줄부터 N마리 바둑이의 무게가 주어진다.
출력설명
첫 번째 줄에 가장 무거운 무게를 출력한다.
테스트케이스
입력예제 | 출력예제 |
---|---|
259 5 81 58 42 33 61 |
242 |
4000 16 27 303 251 121 50 55 123 93 360 84 353 429 765 391 562 77 |
3994 |
100000000 21 27 567 999 234 50 567 123 4734 754 84 35 1353 76 464 4634 65 89 3553 59 38 4135 |
22640 |
해결방법
dfs를 통해서 상태 트리를 이용하여, 리스트에 있는 값을 각각 부분집합으로 더하고 해당 더한 값이 지정한 트럭이 태우는 최대 무게 _max
보다 클 경우로 조건을 끊어서 값을 구한다.
하지만 이럴 경우 리스트의 원소가 많아지면 많아질수록 찾아야하는 부분집합이 너무 많아져서 시간이 오래 걸린다.
이것을 해결하기 위해서 처음 리스트 안에 있는 모든 원소를 더한 값을 total
변수로 만들어서 값을 할당하고, 재귀적으로 함수를 접근할 때, total
의 값에서 지금까지 들어온 node의 합들을 total에서 뺀다.
그럴 경우 total
- sum_max(node를 거치면서 해당 값을 무조건 더하는 변수)
+ sum_current(지금까지 부분집합 적으로 더한 값을 저장한 변수)
를 한다.
이럴 경우 결과로는 밑에 있는 node들을 보지 않아도 전부다 더해지는 값을 알 수 있기 때문에 만약 기존에 저장한 _max
보다 작을 경우는 return을 하여 넘긴다.
동작 시각화
코드
# 시간이 너무 걸리기 때문에 timelimit를 나지 않게 하기 위해서 다른 조건을 추가
# 하나의 매개변수를 더 만들어 값을 계속 더하는 것으로 만든다.
def dfs(x, sum_max, sum_current):
global result_max
# dfs를 도는 도중에 무게를 넘었을 경우 빠져나온다
if _max < sum_max:
return
# 전체는 알 수 있기 때문에 값이 지금의 result_max 보다 작을 경우 굳이 갈 필요가 없다.
if result_max > total - sum_current + sum_max:
return
if x == len(a)+1:
if _max >= sum_max:
if result_max < sum_max:
result_max = sum_max
else:
dfs(x+1, sum_max + a[x-1], sum_current+a[x-1])
dfs(x+1, sum_max, sum_current+a[x-1])
_max, n = map(int, input().split())
a = [int(input()) for _ in range(n)]
ch = [0] * len(a)
total = sum(a)
result_max = 0
dfs(1, 0, 0)
print(result_max)
댓글남기기