πŸ“š Study/Baekjoon

[Gold IV] 32187 - 급식 배식

윰갱 2025. 5. 10. 21:31

문제

β€Š1λΆ€ν„° NκΉŒμ§€μ˜ λ²ˆν˜Έκ°€ λΆ™μ–΄μžˆλŠ” N개의 λ°°μ‹λŒ€κ°€ μžˆλ‹€. i번 λ°°μ‹λŒ€μ—μ„œλŠ” i번 μŒμ‹μ„ 배식받을 수 μžˆλ‹€. Mλͺ…μ˜ 학생듀이 μŒμ‹μ„ λ°›κΈ° μœ„ν•΄ 쀄을 μ„°λ‹€.

각 학생은 νŠΉμ • μŒμ‹μ„ 배식받을 수 있고, 배식받은 μŒμ‹μ— ν•΄λ‹Ήν•˜λŠ” 만큼 행볡도가 μƒμŠΉν•œλ‹€. ꡬ체적인 κ·œμΉ™μ€ λ‹€μŒκ³Ό κ°™λ‹€.

  • β€Šj번 학생은 배식받을 수 μžˆλŠ” μŒμ‹μ˜ 번호 pj,1,pj,2,β‹―,pj,ljκ°€ μ •ν•΄μ Έ μžˆλ‹€. 각 학생은 같은 μŒμ‹μ„ μ΅œλŒ€ ν•œ 번만 배식받을 수 μžˆλ‹€.
  • β€Šj번 학생이 pj,k번 μŒμ‹μ„ 배식받을 경우 ν•™μƒμ˜ 행볡도가 vj,k만큼 μƒμŠΉν•œλ‹€.
  • β€Šj번 학생이 배식받은 μŒμ‹μ€ j+1번 학생이 배식받을 수 μ—†λ‹€. (1≤j≤M−1)β€Š

μ΄ˆκΈ°μ— λͺ¨λ“  ν•™μƒμ˜ ν–‰λ³΅λ„λŠ” 0이닀. ν•™μƒλ“€μ˜ 행볡도 합이 μ΅œλŒ€κ°€ λ˜λ„λ‘ 배식을 μ§„ν–‰ν•΄ 보자!

μž…λ ₯

첫 번째 쀄에 두 μ •μˆ˜ Nκ³Ό M이 곡백으둜 κ΅¬λΆ„λ˜μ–΄ μ£Όμ–΄μ§„λ‹€. (1≤N,M≤105)β€Š

이후 각 학생이 먹을 수 μžˆλŠ” μŒμ‹μ— λŒ€ν•œ 정보가 M개의 쀄에 걸쳐 μ£Όμ–΄μ§„λ‹€.

μ •λ³΄μ˜ j번째 μ€„μ—λŠ” j번 학생이 먹을 수 μžˆλŠ” μŒμ‹μ˜ 개수λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μ •μˆ˜ ljκ°€ κ°€μž₯ λ¨Όμ € μ£Όμ–΄μ§€κ³ , 이후 2lj개의 μ •μˆ˜ pj,1,vj,1,pj,2,vj,2,β‹―,pj,lj,vj,ljκ°€ 곡백으둜 κ΅¬λΆ„λ˜μ–΄ μ£Όμ–΄μ§„λ‹€. μ΄λ•Œ pj,kλŠ” μ¦κ°€ν•˜λŠ” μˆœμ„œλ‘œ μ£Όμ–΄μ§„λ‹€. (1≤j≤M; 1≤lj≤N; 1≤pj,1<pj,2<β‹―<pj,lj≤N; 1≤vj,k≤109)β€Š

λͺ¨λ“  lj의 합은 105을 λ„˜μ§€ μ•ŠλŠ”λ‹€.

좜λ ₯

ν•™μƒλ“€μ˜ 행볡도 ν•©μ˜ μ΅œλŒ“κ°’μ„ 좜λ ₯ν•œλ‹€.

예제 μž…λ ₯ 1 λ³΅μ‚¬

5 5
2 1 5 2 6
1 2 5
1 3 5
1 4 5
1 5 5

예제 좜λ ₯ 1 λ³΅μ‚¬

26

β€Š1번 학생이 1, 2번 μŒμ‹μ„ 배식받고, 3, 4, 5번 학생이 각각 3, 4, 5번 μŒμ‹μ„ λ°°μ‹λ°›μœΌλ©΄, ν•™μƒλ“€μ˜ ν–‰λ³΅λ„μ˜ 합은 (5+6)+0+5+5+5=26이 λœλ‹€. 이 방법보닀 ν–‰λ³΅λ„μ˜ 합을 크게 ν•  수 μžˆλŠ” 방법은 μ—†μœΌλ―€λ‘œ, 닡은 26이 λœλ‹€.


# 풀이 방법

  • food_list[p]: μŒμ‹ pλ₯Ό μ›ν•˜λŠ” (학생 번호, λ§Œμ‘±λ„) 리슀트
  • 각 μŒμ‹μ— λŒ€ν•΄, κ·Έ μŒμ‹μ„ μ›ν•˜λŠ” 학생듀을 μˆœμ„œλŒ€λ‘œ λ³΄λ©΄μ„œ:
    • ν˜„μž¬ 학생이 이전 학생 λ°”λ‘œ λ‹€μŒμ΄λΌλ©΄→ 이전-μ΄μ „κΉŒμ§€μ˜ μ΅œλŒ€κ°’ + ν˜„μž¬ λ§Œμ‘±λ„μ™€ λΉ„κ΅ν•΄μ„œ 더 큰 κ°’ 선택
    • → μ—°μ†λœ 두 ν•™μƒμ΄λ―€λ‘œ 같이 먹을 수 μ—†μŒ
    • κ·Έ μ™Έμ˜ 경우 (연속 μ•„λ‹˜)
    • → κ·Έλƒ₯ μ΄μ „κΉŒμ§€μ˜ μ΅œλŒ€ λ§Œμ‘±λ„μ— ν˜„μž¬ λ§Œμ‘±λ„λ₯Ό 더함
  • 즉, μŒμ‹λ³„λ‘œ μ΅œλŒ€ λ§Œμ‘±λ„ 합을 κ΅¬ν•˜λŠ” DPλ₯Ό μˆ˜ν–‰
  • μ΅œμ’…μ μœΌλ‘œ, λͺ¨λ“  μŒμ‹μ˜ μ΅œλŒ€ λˆ„μ  λ§Œμ‘±λ„ 합을 λ”ν•˜λ©΄ μ •λ‹΅

→ dp문제 ν‘ΈλŠ”κ±° μ—¬μ „νžˆ μ΅μˆ™ν•˜μ§€ μ•ŠμŒ πŸ₯²


# μ½”λ“œ

import sys
sys.stdin = open("input.txt","r")

n, m = map(int, sys.stdin.readline().split())

food_list = [[] for _ in range(n+1)] # μŒμ‹λ³„λ‘œ (ν•™μƒλ²ˆν˜Έ, λ§Œμ‘±λ„) μ €μž₯
hpy_dp = [[] for _ in range(n+1)] # λˆ„μ  ν–‰λ³΅μ§€μˆ˜ μ €μž₯

for i in range(1, m+1): # λͺ¨λ“  학생
    tmp = list(map(int,sys.stdin.readline().split()))
    for j in range(tmp[0]):
        food = tmp[2*j+1]
        hpy = tmp[2*j+2]
        food_list[food].append((i,hpy))

result_hpy = 0
for food in range(1,n+1):
    # μŒμ‹μ„ 먹을 수 μžˆλŠ” 학생이 μ—†λŠ” 경우
    if len(food_list[food]) == 0: continue

    hpy_dp[food].append(0)
    hpy_dp[food].append(food_list[food][0][1]) # 첫번째 ν•™μƒμ˜ λ§Œμ‘±λ„ μ €μž₯

    for i in range(1, len(food_list[food])):
        curr_stu, curr_hpy = food_list[food][i]
        pre_stu, _ = food_list[food][i-1]

        hpy_dp[food].append(hpy_dp[food][-1]+curr_hpy)
        
        # 직전 학생이 이 μŒμ‹ λ°°μ •λ°›μ•˜μœΌλ©΄ μˆ˜μ •ν•΄μ•Ό 함
        if pre_stu + 1 == curr_stu:
            tmp_hpy = hpy_dp[food][-3] + curr_hpy
            if hpy_dp[food][-2] < tmp_hpy:
                hpy_dp[food][-1] = tmp_hpy
            else:
                hpy_dp[food][-1] = hpy_dp[food][-2]
    
    result_hpy += hpy_dp[food][-1]


print(result_hpy)

# μ°Έκ³ 


μ•„λž˜ 쑰건을 μ•„μ˜ˆ λ¬΄μ‹œν•˜κ³  ν‘Ό μ½”λ“œ..

(1) 같은 μŒμ‹μ„ μ—¬λŸ¬λͺ…이 배식받을 수 μžˆλŠ”κ±°

(2) j번 학생이 배식받은 μŒμ‹μ€ j+1번 학생이 배식받을 수 μ—†λŠ”

import sys
sys.stdin = open("input.txt","r")
n, m = map(int,sys.stdin.readline().split()) # n: λ°°μ‹λŒ€, m: 학생 수
food = [0] * (n+1)
for _ in range(m):
    s = list(map(int,sys.stdin.readline().split()))
    for i in range(s[0]): # μŒμ‹μ˜ 길이만큼 반볡문 돌기
        j = 2 * i + 1
        # s[j]: μŒμ‹ 이름 / s[j+1]: λ§Œμ‘±λ„
        if food[s[j]] < s[j+1]:
            food[s[j]] = s[j+1]

print(sum(food))