Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

28-Dolchae #107

Merged
merged 1 commit into from
Feb 20, 2024
Merged

28-Dolchae #107

merged 1 commit into from
Feb 20, 2024

Conversation

Dolchae
Copy link
Collaborator

@Dolchae Dolchae commented Feb 15, 2024

πŸ”— 문제 링크

6236 용돈 관리

βœ”οΈ μ†Œμš”λœ μ‹œκ°„

50λΆ„ + a

✨ μˆ˜λ„ μ½”λ“œ

문제

  • N일 λ™μ•ˆ M번만 톡μž₯μ—μ„œ λˆμ„ λΉΌμ„œ μ“΄λ‹€.
  • 톡μž₯μ—μ„œ K원을 μΈμΆœν•˜κ³  이 돈으둜 ν•˜λ£¨λ₯Ό 보낼 수 μžˆλ‹€λ©΄ κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜κ³ , λͺ¨μžλΌλ©΄ 남은 κΈˆμ•‘μ€ 톡μž₯에 λ„£κ³  λ‹€μ‹œ K원을 μΈμΆœν•œλ‹€.
  • μ •ν™•νžˆ Mλ²ˆμ„ λ§žμΆ”κΈ° μœ„ν•΄ 남은 κΈˆμ•‘μ΄ μ‚¬μš©ν•  κΈˆμ•‘λ³΄λ‹€ λ§Žμ•„λ„ λ‹€μ‹œ 집어넣고 K원을 μΈμΆœν•  수 μžˆλ‹€.
  • μ—¬κΈ°μ„œ μ΅œμ†Œ κΈˆμ•‘ Kλ₯Ό κ΅¬ν•˜λŠ” λ¬Έμ œμ΄λ‹€.

이뢄 탐색

  • 이뢄 νƒμƒ‰μ΄λž€ μ •λ ¬λœ λ¦¬μŠ€νŠΈμ—μ„œ νŠΉμ •ν•œ κ°’μ˜ μœ„μΉ˜λ₯Ό μ°ΎλŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.
  • μΌλ°˜νƒμƒ‰λ³΄λ‹€ 속도가 λΉ λ₯΄λ‹€.
    • 처음과 λ§ˆμ§€λ§‰μ˜ 쀑간값을 선택해 μ΅œμ’… μ°Ύμ•„μ•Όν•˜λŠ” κ°’κ³Ό 크고 μž‘μŒμ„ λΉ„κ΅ν•˜λŠ” 방식을 λ°˜λ³΅ν•˜λ©° νƒμƒ‰ν•œλ‹€.

μ½”λ“œ

import sys

input = sys.stdin.readline

n, m = map(int, input().split())

money = []
for _ in range(n):
    money.append(int(input()))
start = max(money)  
end = sum(money)  
  • nκ³Ό m을 μž…λ ₯λ°›κ³  money에 각각의 날에 μ‚¬μš©ν•  κΈˆμ•‘μ„ μž…λ ₯λ°›μ•„ 리슀트둜 μ €μž₯ν•œλ‹€.
  • 이뢄 탐색을 ν•˜κΈ° μœ„ν•΄ start와 end λ³€μˆ˜λ₯Ό λ§Œλ“ λ‹€.
    • startλŠ” κ°€μž₯ μž‘μ€ λ²”μœ„λ₯Ό λ‚˜νƒ€λ‚΄λŠ”λ°, 적어도 돈의 μ΅œλŒ“κ°’μ€ μ“Έ κ²ƒμ΄λ―€λ‘œ max(money)둜 μ§€μ •ν•œλ‹€.
    • endλŠ” κ°€μž₯ 큰 λ²”μœ„ 끝을 λ‚˜νƒ€λ‚΄λ©° ν•œλ²ˆμ— μΈμΆœν•΄ λ‹€ μ“°λŠ” κ²½μš°κ°€ 이λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

ans = 0
while start <= end:
    mid = (start + end) // 2

    total = 0
    cnt = 0
    for x in money:
        if total + x <= mid:
            total += x
        else:
            cnt += 1
            total = 0
            total += x
    if total:  # λ§ˆμ§€λ§‰ λˆμ— λŒ€ν•΄μ„œ total에 κΈˆμ•‘μ΄ 있으면 cnt++ 처리.
        cnt += 1
  • 후에 좜λ ₯ν•  μ΅œμ†Œ k 값인 ansλ₯Ό 0으둜 μ„ μ–Έν•΄μ€€λ‹€.
  • while문을 λ°˜λ³΅ν•˜λ©° 이뢄 탐색을 μ§„ν–‰ν•œλ‹€.
    • midλŠ” 탐색 쀑인 λ²”μœ„μ˜ 쀑간값을, total은 ν˜„μž¬κΉŒμ§€μ˜ 총 μ‚¬μš© κΈˆμ•‘μ„, cntλŠ” ν˜„μž¬κΉŒμ§€μ˜ 인좜 횟수λ₯Ό μ €μž₯ν•œλ‹€.
    • money 리슀트λ₯Ό μˆœνšŒν•˜λ©΄μ„œ ν˜„μž¬ total에 남은 κΈˆμ•‘μ„ λ”ν–ˆμ„ λ•Œ mid(인좜 κΈˆμ•‘)보닀 μž‘κ±°λ‚˜ κ°™λ‹€λ©΄ ν˜„μž¬ λ‚ μ˜ μ‚¬μš© κΈˆμ•‘μ„ total에 더해쀀닀.
    • 그렇지 μ•Šλ‹€λ©΄(mid 보닀 큰 경우) 인좜 횟수λ₯Ό μ¦κ°€μ‹œν‚€κ³  toatl을 λ‹€μ‹œ 0으둜 μ΄ˆκΈ°ν™”ν•œ ν›„ ν˜„μž¬ λ‚ μ˜ μ‚¬μš© κΈˆμ•‘μ„ total에 λ”ν•œλ‹€.
  • for문이 λλ‚œ 후에 total에 남은 κΈˆμ•‘μ΄ μžˆλ‹€λ©΄ 인좜 횟수λ₯Ό 1 더해쀀닀.

while start <= end:
    ```

    if cnt > m:  
        start = mid + 1
    else:  
        end = mid - 1
        ans = mid

print(ans)
  • 인좜 횟수 cntκ°€ m보닀 크닀면 인좜 κΈˆμ•‘μ„ λŠ˜λ €μ•Ό ν•˜λ―€λ‘œ startλ₯Ό mid+1둜 μ„€μ •ν•œλ‹€.
  • 그렇지 μ•Šλ‹€λ©΄ 인좜 κΈˆμ•‘μ„ 쀄여야 ν•˜λ―€λ‘œ endλ₯Ό mid-1둜 μ„€μ •ν•˜κ³  ν˜„μž¬ midλ₯Ό μ •λ‹΅μœΌλ‘œ μ €μž₯ν•œλ‹€.


전체 μ½”λ“œ

import sys

input = sys.stdin.readline

n, m = map(int, input().split())

money = []
for _ in range(n):
    money.append(int(input()))

start = max(money)
end = sum(money)

ans = 0
while start <= end:
    mid = (start + end) // 2

    total = 0
    cnt = 0
    for x in money:
        if total + x <= mid:
            total += x
        else:
            cnt += 1
            total = 0
            total += x
    if total:  
        cnt += 1

    if cnt > m:  
        start = mid + 1
    else:  
        end = mid - 1
        ans = mid

print(ans)

πŸ“š μƒˆλ‘­κ²Œ μ•Œκ²Œλœ λ‚΄μš©

이뢄 탐색을 κ³΅λΆ€ν•˜μ˜€λ‹€. κ°œλ… μžμ²΄λŠ” κ·Έλ ‡κ²Œ μ–΄λ ΅κ²Œ λŠκ»΄μ§€μ§€λŠ” μ•Šμ•˜λŠ”λ° μ—­μ‹œλ‚˜ 문제λ₯Ό ν’€λ €κ³  ν•˜λ‹ˆ 많이 μ–΄λ €μ› λ‹€πŸ₯²πŸ˜‚


ν•™μŠ΅ μ°Έκ³  λΈ”λ‘œκ·Έ
μ½”λ“œ μ°Έκ³  λΈ”λ‘œκ·Έ

Copy link
Collaborator

@9kyo-hwang 9kyo-hwang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이진 탐색... μ°Έ 적응 μ•ˆλ˜λŠ” μœ ν˜•μ΄μ£ 
저도 μ—¬μ „νžˆ μ©”μ©”λ§΅λ‹ˆλ‹€...

κ·Έλž˜λ„ μ—΄μ‹¬νžˆ λ…Έλ ₯ν•΄λ΄…μ‹œλ‹€!

Comment on lines +18 to +28
total = 0
cnt = 0
for x in money:
if total + x <= mid:
total += x
else:
cnt += 1
total = 0
total += x
if total:
cnt += 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이진 탐색, μ •ν™•νžˆλŠ” λ§€κ°œλ³€μˆ˜ νƒμƒ‰μ˜ 경우 μ–΄λ €μš΄ 문제일 수둝 start, end 값을 λ³€κ²½μ‹œν‚€κΈ° μœ„ν•œ 쑰건 νŒλ³„ μ½”λ“œκ°€ 많이 κΈΈμ–΄μ§‘λ‹ˆλ‹€.
이 λ¬Έμ œμ—μ„œλŠ” μ—¬κΈ° 뢀뢄이 되겠죠?

def getTakeoutCnt(mid):
    total, take_out = 1, 0 
    for used in used_money:
        if total + used > mid:
            take_out += 1
            total = used
        else:
            total += used
        
    return take_out

보톡은 check() 같은 이름을 많이 μ‚¬μš©ν•˜λŠ”λ°, μ—¬κΈ°λŠ” μΈμΆœν•˜λŠ” 횟수λ₯Ό κ΅¬ν•˜λŠ” κ±°λ‹ˆκΉŒ μ΄λ ‡κ²Œ 이름 μ§€μ–΄λ΄€μŠ΅λ‹ˆλ‹€.

while lo <= hi:
    mid = (lo + hi) // 2

    if getTakeoutCnt(mid) > M:
        lo = mid + 1
    else:
        hi = mid - 1

그럼 이진탐색 νŒŒνŠΈλŠ” μ΄λ ‡κ²Œ μ‹¬ν”Œν•΄μ§€μ£ ?

Comment on lines +31 to +32
| 27μ°¨μ‹œ| 2024.02.15 | 이진 탐색 | [6236 용돈 관리](https://www.acmicpc.net/problem/1302) | [#107](https://github.com/AlgoLeadMe/AlgoLeadMe-3/pull/107) |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

λ‘˜ λ‹€ 27μ°¨μ‹œλ‘œ μ ν˜€μžˆλ„€μš” γ…‹γ…‹

Copy link
Member

@xxubin04 xxubin04 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이번 λ¬Έμ œλŠ” 이진 탐색 λ¬Έμ œμ˜€λŠ”λ° 많이 ν—€λ§Έμ—ˆλ„€μš”πŸ˜‚
같이 이진 탐색을 ν•œλ²ˆ μ •λ³΅ν•΄λ΄…μ‹œλ‹€πŸ˜πŸ’ͺ🏻
수고 λ§ŽμœΌμ…¨μŠ΅λ‹ˆλ‹€!!

Copy link
Member

@gjsk132 gjsk132 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μ „ endλ₯Ό λͺ¨λ“  κ²½μš°μ—μ„œ λ‚˜μ˜¬ 수 μžˆλŠ” 큰 κ°’μœΌλ‘œ μ„€μ •ν•΄μ€¬λŠ”λ°, sum(money)둜 ν•˜λŠ” 방법도 μžˆλ„€μš”!

Comment on lines +30 to +34
if cnt > m:
start = mid + 1
else:
end = mid - 1
ans = mid
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

λ§ˆμ§€λ§‰μ— κ²°κ΅­ start와 endκ°€ κ°™μ•„μ‘Œμ„ λ•Œ, ν•΄λ‹Ή 값이 정닡이 되고, start와 endκ°€ μ—­μ „λ©λ‹ˆλ‹€.

μ—¬κΈ°μ„œ, ν•΄λ‹Ή 문제의 κ²½μš°μ—λŠ” endκ°€ mid-1이 λ˜λ©΄μ„œ μžμ—°μŠ€λŸ½κ²Œ start에 μžˆλŠ” (λ§ˆμ§€λ§‰ λ‹¨κ³„μ—μ„œ) λ³€ν•˜μ§€ μ•Šμ€ 값이 정닡이 되게 λ©λ‹ˆλ‹€.

κ·Έλž˜μ„œ ansλ₯Ό λ”°λ‘œ μ •μ˜ν•˜μ§€ μ•Šκ³  print(start)둜 λ°”λ‘œ 좜λ ₯ν•΄μ€˜λ„ 정닡이 될 수 μžˆμŠ΅λ‹ˆλ‹€.

start = max(money)
end = sum(money)

while start <= end:
    mid = (start + end) // 2

    total = 0
    cnt = 0
    for x in money:
        if total + x <= mid:
            total += x
        else:
            cnt += 1
            total = 0
            total += x
    if total:  
        cnt += 1

    if cnt > m:  
        start = mid + 1
    else:  
        end = mid - 1

print(start)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants