매일매일 문제를 풀고 있다... 오늘은 아마 프로그래머스 푸는 사람이면 다 풀어봤을 '구명보트' 문제를 풀어보자...!
코딩테스트 연습 - 구명보트
무인도에 갇힌 사람들을 구명보트를 이용하여 구출하려고 합니다. 구명보트는 작아서 한 번에 최대 2명씩 밖에 탈 수 없고, 무게 제한도 있습니다. 예를 들어, 사람들의 몸무게가 [70kg, 50kg, 80kg, 5
programmers.co.kr
그리디 알고리즘을 풀어봤다. 그리디 알고리즘은 함정에 빠지기 쉬운 문제로 조건을 잘 살펴야 한다.
문제 설명
무인도에 갇힌 사람들을 구명보트를 이용하여 구출하려고 합니다. 구명보트는 작아서 한 번에 최대 2명씩밖에 탈 수 없고, 무게 제한도 있습니다.
예를 들어, 사람들의 몸무게가 [70kg, 50kg, 80kg, 50kg]이고 구명보트의 무게 제한이 100kg이라면 2번째 사람과 4번째 사람은 같이 탈 수 있지만 1번째 사람과 3번째 사람의 무게의 합은 150kg이므로 구명보트의 무게 제한을 초과하여 같이 탈 수 없습니다.
구명보트를 최대한 적게 사용하여 모든 사람을 구출하려고 합니다.
제한사항
- 무인도에 갇힌 사람은 1명 이상 50,000명 이하입니다.
- 각 사람의 몸무게는 40kg 이상 240kg 이하입니다.
- 구명보트의 무게 제한은 40kg 이상 240kg 이하입니다.
- 구명보트의 무게 제한은 항상 사람들의 몸무게 중 최댓값보다 크게 주어지므로 사람들을 구출할 수 없는 경우는 없습니다.
입출력 예
people | limit | return |
[70, 50, 80, 50] | 100 | 3 |
[70, 80, 50] | 100 | 3 |
50 + 50 -> 1개
70 -> 1개
80 -> 1개
합 3개의 구명보트가 필요하다.
풀이 방법
이 문제는 효율성이 있어서 pop이나 append를 남발하면 안 된다. 그러므로 배열 삽입 삭제 없이 인덱스를 움직이는 것으로 문제를 해결했다. 변수 First와 변수 Last를 선언하여 케이스별로 컨트롤했다.
🔴 people [First]와 People [Last]를 더했을 때 Limit값 이하 -> First+1 , Last-1 하고 Return 값도 하나 늘림.
🟡 people [First]와 People [Last]를 더했을 때 Limit값 초과 -> Last -1 하고 Return 값도 하나 늘림.
마지막으로 Last가 First변수 같으면 Return 값을 하나 늘리고 동작을 멈췄고(🟢), 크면 그냥 동작을 멈췄다(🔵).
예를 들면 People 리스트가 [10,20,30,40,60,60,70,80], Limit는 70일 경우.
First | Last | People[First]+People[Last] | Answer | Case | |
0 | 7 | People[0]+People[7] = 90 | Last-=1 | 1 | 🟡 |
0 | 6 | People[0]+People[6] = 80 | Last-=1 | 2 | 🟡 |
0 | 5 | People[0]+People[5] = 70 | First+=1, Last-=1 | 3 | 🔴 |
1 | 4 | People[1]+People[4] = 70 | Last-=1 | 4 | 🟡 |
1 | 3 | People[1]+People[3] = 70 | First+=1, Last-=1 | 5 | 🔴 |
2 | 2 | 6 | 🟢 |
왜?
해당 문제의 포인트는 보트에 두 명을 태울 수 있는지 한 명을 태울 수 있는지 판단하는 것이라고 생각한다.
이걸 판단할 수 있는 방법은 태우지 않은 사람 중 무게가 가장 많이 나가는 사람과 가장 적게 나가는 사람을 더하여 Limit이 넘는지 판단하고 Limit을 넘으면 무게가 많이 나가는 사람은 구명보트에 태워 보내는 게 가장 적절하다고 생각하여 해당 풀이를 적용하였다.
코드
def solution(people, limit):
answer = 0
people.sort()# 정렬
if len(people)==1:# 1은 웬만하면 예외처리 하는게 좋음.
return 1
first=0# 처음과 끝 인덱스 설정
last=len(people)-1#
while True:
if last==first:#🟢
# 해당 케이스는 🟡케이스로 끝이 난 경우인데,
# 이럴 경우는 앞에 있는 사람은 따른 보트에 태워보내야하기 때문에 보트를 추가한다.
answer+=1
break
if last<first:#🔵
#이 경우는 완벽히 다 보트를 탄 경우이기 때문에 보트를 추가하지 않아도 된다.
break
if people[first]+people[last]<=limit: #🔴 # 두명씩 태워보내는 케이스
answer+=1
first+=1
last-=1
else:#🟡 #한명씩 태워보내는 케이스
last-=1
answer+=1
return answer
실행 결과
'코딩테스트 대비' 카테고리의 다른 글
[프로그래머스] 숫자 게임 (0) | 2021.10.11 |
---|---|
[프로그래머스] 기지국 설치 (0) | 2021.08.12 |
[프로그래머스] 줄 서는 방법 (0) | 2021.07.18 |
[프로그래머스] 단어 변환 (0) | 2021.07.17 |
[Baekjoon/백준] 수 분해_ 1437 (0) | 2021.07.10 |