λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

Algorithm/CodingTest - Python

Algorithm ) Greedy

λ°˜μ‘ν˜•

μ½”λ”©ν…ŒμŠ€νŠΈμ—μ„œ κ°€μž₯ 좜제 λΉˆλ„κ°€ 높은 λ¬Έμ œλŠ” 그리디, κ΅¬ν˜„,  DFS/BFS λ₯Ό ν™œμš©ν•œ 탐색 문제라고 ν•œλ‹€! 

μˆœμ„œλŒ€λ‘œ ν¬μŠ€νŒ… ν•  μ˜ˆμ •μ΄κ³ , μ˜€λŠ˜μ€ 기초 그리디 λ¬Έμ œμ— λŒ€ν•΄ λ‹€λ€„λ³΄κ³ μž ν•œλ‹€ 

 

 

 

πŸ› 그리디 μ•Œκ³ λ¦¬μ¦˜ : νƒμš•λ²•, ν˜„μž¬ μƒν™©μ—μ„œ μ§€κΈˆ λ‹Ήμž₯ 쒋은 κ²ƒλ§Œ κ³ λ₯΄λŠ” 방법 

- 일반적으둜 그리디 μ•Œκ³ λ¦¬μ¦˜μ€ 문제λ₯Ό ν’€κΈ° μœ„ν•œ μ΅œμ†Œν•œμ˜ 아이디어λ₯Ό λ– μ˜¬λ¦΄ 수 μžˆλŠ” λŠ₯λ ₯을 μš”κ΅¬ 

- μ •λ‹Ήμ„± 뢄석이 μ€‘μš” : λ‹¨μˆœνžˆ κ°€μž₯ μ’‹μ•„λ³΄μ΄λŠ” 것을 반볡적으둜 선택해도 졜적의 ν•΄λ₯Ό ꡬ할 수 μžˆλŠ”μ§€ κ²€ν† 

- 일반적인 μƒν™©μ—μ„œ 그리디 μ•Œκ³ λ¦¬μ¦˜μ€ 졜적의 ν•΄λ₯Ό 보μž₯ν•  수 없을 λ•Œκ°€ 많음 

- ν•˜μ§€λ§Œ, μ½”λ”©ν…ŒμŠ€νŠΈμ—μ„œ λŒ€λΆ€λΆ„μ˜ 그리디 λ¬Έμ œλŠ” νƒμš•λ²•μœΌλ‘œ 얻은 ν•΄κ°€ 졜적의 ν•΄κ°€ λ˜λŠ” μƒν™©μ—μ„œ 이λ₯Ό μΆ”λ‘ ν•  수 μžˆμ–΄μ•Ό 풀리도둝 좜제됨

 

 

 

πŸ’΅λŒ€ν‘œμ μΈ 그리디 μ•Œκ³ λ¦¬μ¦˜ 문제 ! κ±°μŠ€λ¦„λˆ 

500원, 100원, 50원, 10μ›μ§œλ¦¬ 동전이 λ¬΄ν•œνžˆ 쑴재

-> μ†λ‹˜μ—κ²Œ κ±°μŠ¬λŸ¬μ€˜μ•Ό ν•  돈이 N원일 λ•Œ κ±°μŠ¬λŸ¬μ€˜μ•Ό ν•  λ™μ „μ˜ μ΅œμ†Œ 개수 ?

(단, 거슬러 μ€˜μ•Ό ν•  돈 N은 항상 10의 배수)

 

 

⚑️문제 ν•΄κ²° 아이디어 

- 졜적의 ν•΄λ₯Ό κ°€μž₯ λΉ λ₯΄κ²Œ κ΅¬ν•˜κΈ° μœ„ν•΄μ„œ κ°€μž₯ 큰 ν™”νλ‹¨μœ„ λΆ€ν„° λˆμ„ 거슬러 μ£ΌλŠ” 것

- N원을 거슬러 쀄 λ•Œ, 500μ›μœΌλ‘œ 거슬러 쀄 수 μžˆμ„ 만큼 거슬러 μ£Όκ³ , κ·Έ λ‹€μŒ 100 50 10 μ›μ§œλ¦¬ 동전을 μ°¨λ‘€λŒ€λ‘œ 거슬러 μ£ΌκΈ°

 

n = 1260
count = 0

# 큰 λ‹¨μœ„μ˜ 화폐뢀터 μ°¨λ‘€λ‘œ ν™•μΈν•˜κΈ°
array = [500, 100, 50, 10]

for coin in array:
    count += n // coin # ν•΄λ‹Ή ν™”νλ‘œ 거슬러 쀄 수 μžˆλŠ” 동전 μ„ΈκΈ°
    n %= coin

print(count)

 

πŸ₯¦ μ •λ‹Ήμ„± 뢄석 

- κ°€μ§€κ³  μžˆλŠ” 동전 μ€‘μ—μ„œ 큰 λ‹¨μœ„κ°€ 항상 μž‘μ€ λ‹¨μœ„μ˜ λ°°μˆ˜μ΄λ―€λ‘œ μž‘μ€ λ‹¨μœ„μ˜ 동전듀을 μ’…ν•©ν•΄ λ‹€λ₯Έ ν•΄κ°€ λ‚˜μ˜¬ 수 μ—†μŒ

- λŒ€λΆ€λΆ„μ˜ 그리디 μ•Œκ³ λ¦¬μ¦˜ λ¬Έμ œμ—μ„œλŠ” 이처럼 문제 풀이λ₯Ό μœ„ν•œ μ΅œμ†Œν•œμ˜ 아이디어λ₯Ό λ”μ˜¬λ¦¬κ³  이것이 μ •λ‹Ήν•œμ§€ κ²€ν† ν•  수 μžˆμ–΄μ•Ό 닡을 λ„μΆœ ν•  수 있음 

 

🌈 μ‹œκ°„ λ³΅μž‘λ„ 뢄석

- ν™”νμ˜ μ’…λ₯˜κ°€ K 라고 ν•  λ•Œ, μ†ŒμŠ€μ½”λ“œμ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(K)

- μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” κ±°μŠ¬λŸ¬μ€˜μ•Όν•˜λŠ” κΈˆμ•‘κ³ΌλŠ” 무관, ν™”νμ˜ μ’…λ₯˜λ§ŒνΌ λ°˜λ³΅ν•˜λ©΄ λ¬Έμ œν•΄κ²° 

 

 

 

μ–΄λ–€ μ½”λ”©ν…ŒμŠ€νŠΈ 문제λ₯Ό λ§Œλ‚¬μ„ λ•Œ , λ°”λ‘œ 문제 μœ ν˜•μ„ νŒŒμ•…ν•˜κΈ° μ–΄λ ΅λ‹€λ©΄ 그리디 μ•Œκ³ λ¦¬μ¦˜μ„ μ˜μ‹¬ν•˜κ³ , 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλŠ” νƒμš•μ μΈ 해결법이 μ‘΄μž¬ν•˜λŠ”μ§€ κ³ λ―Όν•΄λ³΄μž. 였랜 μ‹œκ°„μ„ 고민해도 그리디 μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ 해결방법을 찾을 수 μ—†λ‹€λ©΄, 이후에 λ‹€λ£¨κ²Œ 될 λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ΄λ‚˜ κ·Έλž˜ν”„ μ•Œκ³ λ¦¬μ¦˜ λ“±μœΌλ‘œ 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλŠ”μ§€ 재차 κ³ λ―Ό ! 

 

μ‹€μ œλ‘œ κ±°μŠ€λ¦„λˆ λ¬Έμ œμ—μ„œ λ™μ „μ˜ λ‹¨μœ„κ°€ μ„œλ‘œ 배수 ν˜•νƒœκ°€ μ•„λ‹ˆλΌ λ¬΄μž‘μœ„λ‘œ μ£Όμ–΄μ§„ κ²½μš°μ—λŠ” 그리디 μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ ν•΄κ²° ν•  수 μ—†λ‹€. ν™”νμ˜ λ‹¨μœ„κ°€ λ¬΄μž‘μœ„λ‘œ μ£Όμ–΄μ§„ λ¬Έμ œλŠ” λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μœΌλ‘œ ν•΄κ²°ν•  수 μžˆλ‹€. 

 

 

μ‹€μ „ 문제 풀이

 

1οΈβƒ£λ¬Έμ œ 1 : 큰 수의 법칙 

- λ‹€μ–‘ν•œ 수둜 이루어진 배열이 μžˆμ„ λ•Œ μ£Όμ–΄μ§„ μˆ˜λ“€μ„ M 번 λ”ν•˜μ—¬ κ°€μž₯ 큰 수λ₯Ό λ§Œλ“œλŠ” 법칙이닀

- 단, λ°°μ—΄μ˜ νŠΉμ •ν•œ μΈλ±μŠ€μ— ν•΄λ‹Ήν•˜λŠ” μˆ˜κ°€ μ—°μ†ν•΄μ„œ Kλ²ˆμ„ μ΄ˆκ³Όν•˜μ—¬ λ”ν•΄μ§ˆ 수 μ—†λŠ” 것이 νŠΉμ§•μ΄λ‹€

- 예λ₯Ό λ“€μ–΄ μˆœμ„œλŒ€λ‘œ 2,4,5,4,6 으둜 이루어진 배열이 μžˆμ„ λ•Œ M이 8이고, Kκ°€ 3이라고 κ°€μ •ν•΄λ³΄μž. 

이 경우 νŠΉμ •ν•œ 인덱슀의 μˆ˜κ°€ μ—°μ†ν•΄μ„œ 3λ²ˆκΉŒμ§€λ§Œ λ”ν•΄μ§ˆ 수 μžˆμœΌλ―€λ‘œ 6+6+6+5+6+6+6+5 인 46이 λœλ‹€. 

- 단, μ„œλ‘œ λ‹€λ₯Έ μΈλ±μŠ€μ— ν•΄λ‹Ήν•˜λŠ” μˆ˜κ°€ 같은 κ²½μš°μ—λ„ μ„œλ‘œ λ‹€λ₯Έ κ²ƒμœΌλ‘œ κ°„μ£Ό. λ‘λ²ˆμ§Έ 인덱슀의 4와 λ„€λ²ˆμ§Έ 인덱슀의 4λŠ” λ‹€λ₯΄λ‹€. 

 

 

πŸ“Œ μž…λ ₯쑰건 

- 첫째 쀄에 N, M, K 의 μžμ—°μˆ˜κ°€ μ£Όμ–΄μ§€λ©°, 곡백으둜 ꡬ뢄

- λ‘˜μ§Έ 쀄에 N개의 μžμ—°μˆ˜κ°€ μ£Όμ–΄μ§€λ©°, 곡백으둜 ꡬ뢄. 단 각각의 μžμ—°μˆ˜λŠ” 1 이상 10000μ΄ν•˜μ˜ 수둜 μ£Όμ–΄μ§„λ‹€. 

- μž…λ ₯으둜 μ£Όμ–΄μ§€λŠ” KλŠ” 항상 M보닀 μž‘κ±°λ‚˜ κ°™λ‹€ 

 

πŸ“Œ 좜λ ₯쑰건 

- 큰 수의 법칙에 따라 더해진 닡을 좜λ ₯ν•œλ‹€.

 

 

 

 

문제 ν•΄κ²° 아이디어 : κ°€μž₯ 큰 μˆ˜μ™€ λ‘λ²ˆμ§Έλ‘œ 큰 수 만 μ €μž₯ν•˜κ³ , μ—°μ†μœΌλ‘œ μ΅œλŒ€ k번 더할 수 μžˆμœΌλ―€λ‘œ κ°€μž₯ 큰수λ₯Ό k번 λ”ν•˜κ³  두 번째둜 큰수λ₯Ό 1번만 λ”ν•˜λŠ” 것을 λ°˜λ³΅ν•˜μž! 

# N,M,K 곡백으둜 κ΅¬λΆ„ν•˜μ—¬ μž…λ ₯λ°›κΈ° , N개의 수λ₯Ό 곡백으둜 κ΅¬λΆ„ν•˜μ—¬ μž…λ ₯λ°›κΈ°
n, m, k = map(int, input().split())
data = list(map(int, input().split()))

data.sort() # μž…λ ₯받은 수λ₯Ό μ •λ ¬
first = data[n - 1] #κ°€μž₯ 큰수
second = data[n - 2] #λ‘λ²ˆμ§Έλ‘œ 큰수

result = 0

while True:
    for i in range(k): # κ°€μž₯ 큰 수λ₯Ό k번 λ”ν•˜κΈ°
        if m == 0: # m이 0이라면 반볡문 νƒˆμΆœ
            break
        result += first
        m -= 1 # 더할 λ•Œ λ§ˆλ‹€ 1μ”© λΉΌκΈ°
    if m == 0:
        break
    result += second # λ‘λ²ˆμ§Έλ‘œ 큰 수λ₯Ό ν•œλ²ˆλ§Œ λ”ν•˜κΈ°
    m -= 1 # 더할 λ•Œλ§ˆλ‹€ 1μ”© λΉΌκΈ°

print(result)

풀이 1 : λ‹¨μˆœν•˜κ²Œ ν‘ΈλŠ” μ˜ˆμ‹œ -> M의 μˆ˜κ°€ 컀진닀면? μ‹œκ°„μ΄ˆκ³Όμ˜ κ°€λŠ₯성이 μžˆμœΌλ―€λ‘œ, 더 효율적인 풀이 ν•„μš”

# N,M,K 곡백으둜 κ΅¬λΆ„ν•˜μ—¬ μž…λ ₯λ°›κΈ° , N개의 수λ₯Ό 곡백으둜 κ΅¬λΆ„ν•˜μ—¬ μž…λ ₯λ°›κΈ°
n, m, k = map(int, input().split())
data = list(map(int, input().split()))

data.sort() # μž…λ ₯받은 수λ₯Ό μ •λ ¬
first = data[n - 1] #κ°€μž₯ 큰수
second = data[n - 2] #λ‘λ²ˆμ§Έλ‘œ 큰수

# κ°€μž₯ 큰 μˆ˜κ°€ λ”ν•΄μ§€λŠ” 횟수 계산
count = int(m / (k+1)) * k # m을 k+1 둜 λ‚˜λˆˆ λͺ«μ— k κ³±ν•˜κΈ°
count += m % (k + 1) # λ‚˜λˆ„μ–΄ λ–¨μ–΄μ§€μ§€ μ•ŠλŠ” 경우, λ‚˜λ¨Έμ§€ 만큼 ν°μˆ˜κ°€ 더해진닀 

result = 0
result += (count) * first # κ°€μž₯ 큰수 λ”ν•˜κΈ° 
result += (m - count) * second # λ‘λ²ˆμ§Έλ‘œ 큰수 λ”ν•˜κΈ° 

print(result)

풀이 2 : λ°˜λ³΅λ˜λŠ” μˆ˜μ—΄μ— λŒ€ν•΄μ„œ νŒŒμ•… -> κ°€μž₯ 큰 μˆ˜μ™€ λ‘λ²ˆμ§Έλ‘œ 큰 μˆ˜κ°€ λ”ν•΄μ§ˆ λ•Œμ—λŠ” νŠΉμ •ν•œ μˆ˜μ—΄ ν˜•νƒœλ‘œ μΌμ •ν•˜κ²Œ λ°˜λ³΅ν•΄μ„œ λ”ν•΄μ§€λŠ” κ²½ν–₯이 있음 -> κ·Έ κΈΈμ΄λŠ” K + 1 

 

πŸ’₯ M을  K + 1둜 λ‚˜λˆˆ λͺ«μ΄ μˆ˜μ—΄μ΄ λ°˜λ³΅λ˜λŠ” νšŸμˆ˜κ°€ 되고, 여기에 K λ₯Ό κ³±ν•΄μ£Όλ©΄ κ°€μž₯ 큰 μˆ˜κ°€ λ“±μž₯ν•˜λŠ” νšŸμˆ˜κ°€ λœλ‹€ 

λ§Œμ•½μ— λ‚˜λˆ„μ–΄ λ–¨μ–΄μ§€μ§€ μ•ŠλŠ” 경우 λ‚˜λ¨Έμ§€λ§ŒνΌ κ°€μž₯ 큰 μˆ˜κ°€ λ”ν•΄μ§€λ―€λ‘œ 이λ₯Ό 더해쀀닀 ! 

결과적으둜, μ΅œμ’… κ²°κ³Ό 값에 이 횟수 만큼 κ°€μž₯ 큰 수λ₯Ό 더해주고 남은 횟수만큼 λ‘λ²ˆμ§Έλ‘œ 큰 수 λ₯Ό 더해쀀닀 !

 

 

 

GitHub - Suyeon9911/Algorithm-Study: μ•Œκ³ λ¦¬μ¦˜ 곡뢀 레포 πŸ¦‹

μ•Œκ³ λ¦¬μ¦˜ 곡뢀 레포 πŸ¦‹. Contribute to Suyeon9911/Algorithm-Study development by creating an account on GitHub.

github.com

 

 

 

λ°˜μ‘ν˜•