개발야옹

🌼 Greedy Algorithm (탐욕 알고리즘) 본문

Algorithm\CodingTest/이것이 코딩테스트다 with 파이썬

🌼 Greedy Algorithm (탐욕 알고리즘)

kitez 2024. 10. 1. 02:14

이것이 코딩테스트다 with 파이썬

🌼 Greedy Algorithm (탐욕 알고리즘)

  • 현재 상황에서 지금 당장 좋은 것만 고르는 방법
  • 일반적인 상황에서 그리디 알고리즘은 최적의 해를 보장할 수 없다. >> 정당성 분석이 중요!
  • 그러나 코테 문제에서는 일반적으로 탐욕법으로 얻은 해가 최적의 해가 되는 상황에서 이론 추론해야 풀리도록 출제
  • 대표적인 그리디 알고리즘 문제 - 거스름돈 문제

 

📄 <문제1> 1이 될 때까지: 문제 설명

어떠한 수 N이 1이 될 때까지 다음의 두 과정 중 하나를 반복적으로 선택하여 수행하려고 함.

단, 두 번째 연산은 N이 K로 나누어 떨어질 때만 선택할 수 있음.

1. N에서 1을 뺀다.

2. N을 K로 나눈다.

ex) N이 17, K가 4라고 가정. 이때 1번의 과정을 한 번 수행하면 N은 16이 된다. 이후에 2번의 과정을 두 번 수행하면 N은 1이 된다. 결과적으로 전체 과정을 실행한 횟수는 3 이 된다. 

N과 K가 주어질 때 N이 될 때 까지 1번 혹은 2번의 과정을 수행해야 하는 최소 횟수를 구하는 프로그램 작성

# N, K을 공백을 기준으로 구부낳여 입력 받기
N, K = map(int, input().split())

result = 0

while True:
	# N이 K로 나누어 떨어지는 수가 될 때까지 빼기
    target = (N // K) * K
    result += (n - target)
    
    n = target
    # N이 K보다 작을 때(더 이상 K로 나눌 수 없을 때) 반복문 탈출
    if N < K:
    	break
        
    # K로 나누기
    result += 1
    N //= K
# 마지막으로 남은 수에 대하여 1씩 빼기
result += (N -1)
print(result)

 

 

📄 <문제2> 곱하기 혹은 더하기: 문제 설명

각 자리가 숫자(0부터 9)로만 이루어진 문자열 S가 주어졌을 때, 왼쪽부터 오른쪽으로 하나씩 모든 숫자를 확인하며 숫자 사이에 'x' 혹은 '+' 연산자를 넣어 결과적으로 만들어질 수 있는 가장 큰 수를 구하는 프로그램 작성

단, +보다 x를 먼저 계산하는 일반적인 방식과는 달리, 모든 연산은 왼쪽에서부터 순서대로 이루어진다고 가정

ex) 02984 라는 문자열로 만들 수 있는 가장 큰 수는 ((((0+2) * 9) * 8) * 4) = 576입니다. 또한 만들어질 수 있는 가장 큰 수는 항상 20억 이하의 정수가 되도록 입력이 주어진다.

 

  • 대부분의 경우 '+' 보다는 'x'가 더 값을 크게 만듬.
  • 두 수 중에서 하나라도 '0' 혹은 '1'인 경우, 곱하기보다 더하기를 수행하는 것이 효율적
  • 따라서 두 수에 대하여 연산을 진행할 때, 두 수 중에서 하나라도 1 이하인 경우에는 더하며, 두 수가 모두 2 이상인 경우에는 곱하면 정답
strings = list(map(int, input().strip()))

result = 0

for s in strings:
    if s <= 1 or result <= 1:
        result += s
    else:
        result *= s
print(result)

 

 

📄 <문제3> 모험가 길드: 문제설명

한 마을에 모험가가 N명이 있다. 모험가 길드에서는 N명의 모험가를 대상으로 '공포도'를 측정했는데, '공포도'가 높은 모험가는 쉽게 공포를 느껴 위험 상황에서 제대로 대처할 능력이 떨어진다.

모험가 길드장인 00이는 모험가 그룹을 안전하게 구성하고자 공포도가 X인 모험가는 반드시 X명 이상으로 구성한 모험가 그룹에 참여해야 여행을 떠날 수 있도록 규정했다.

  • 풀이 방법
    1. 공포도 오름차순 정렬
    2. 앞에서부터 공포도를 하나씩 확인하며 '현재 그룹에 포함된 모험가의 수'가 '현재 확인하고 있는 공포도' 보다 크거나 같다면 이를 그룹으로 설정하면 된다.
n = int(input())
data =list(map(int, input().split()))
data.sort()

result = 0 # 총 그룹의 수
count = 0 # 현재 그룹에 포함된 모험가의 수

for i in data: # 공포도를 낮은 것부터 하나씩 확인하며
	count += 1 # 현재 그룹에 해당 모험가를 포함시키기
    if count >= i: # 현재 그룹에 포함된 모험가의 수가 현재의 공포도 이상이라면, 그룹 결성
    	result += 1 # 총 그룹의 수 증가
        count = 0 # 현재 그룹에 포함된 모험가의 수 초기화
print(result)
728x90