μ•Œκ³ λ¦¬μ¦˜/브루트포슀

[λ°±μ€€ 19942 πŸ₯‡] λ‹€μ΄μ–΄νŠΈ

1eehyunji 2023. 9. 12. 01:35

https://www.acmicpc.net/problem/19942

 

19942번: λ‹€μ΄μ–΄νŠΈ

μ‹μž¬λ£Œ N개 μ€‘μ—μ„œ λͺ‡ 개λ₯Ό μ„ νƒν•΄μ„œ μ΄λ“€μ˜ μ˜μ–‘λΆ„(λ‹¨λ°±μ§ˆ, νƒ„μˆ˜ν™”λ¬Ό, μ§€λ°©, 비타민)이 일정 이상이 λ˜μ–΄μ•Ό ν•œλ‹€. μ•„λž˜ ν‘œμ— μ œμ‹œλœ 6κ°€μ§€μ˜ μ‹μž¬λ£Œ μ€‘μ—μ„œ λͺ‡ 개λ₯Ό μ„ νƒν•΄μ„œ μ΄λ“€μ˜ μ˜μ–‘λΆ„μ˜ 각

www.acmicpc.net

문제

μ‹μž¬λ£Œ N개 μ€‘μ—μ„œ λͺ‡ 개λ₯Ό μ„ νƒν•΄μ„œ μ΄λ“€μ˜ μ˜μ–‘λΆ„(λ‹¨λ°±μ§ˆ, νƒ„μˆ˜ν™”λ¬Ό, μ§€λ°©, 비타민)이 일정 이상이 λ˜μ–΄μ•Ό ν•œλ‹€. μ•„λž˜ ν‘œμ— μ œμ‹œλœ 6κ°€μ§€μ˜ μ‹μž¬λ£Œ μ€‘μ—μ„œ λͺ‡ 개λ₯Ό μ„ νƒν•΄μ„œ μ΄λ“€μ˜ μ˜μ–‘λΆ„μ˜ 각각 합이 μ΅œμ†Œ 100, 70, 90, 10κ°€ λ˜λ„λ‘ ν•˜λŠ” 경우λ₯Ό μƒκ°ν•΄λ³΄μž. 이 경우 λͺ¨λ“  재료λ₯Ό μ„ νƒν•˜λ©΄ μ‰½κ²Œ ν•΄κ²°λ˜μ§€λ§Œ, μš°λ¦¬λŠ” 쑰건을 λ§Œμ‘±μ‹œν‚€λ©΄μ„œλ„ λΉ„μš©μ΄ μ΅œμ†Œκ°€ λ˜λŠ” 선택을 ν•˜λ €κ³  ν•œλ‹€.

μž¬λ£Œλ‹¨λ°±μ§ˆμ§€λ°©νƒ„μˆ˜ν™”λ¬ΌλΉ„νƒ€λ―Όκ°€κ²©
1 30 55 10 8 100
2 60 10 10 2 70
3 10 80 50 0 50
4 40 30 30 8 60
5 60 10 70 2 120
6 20 70 50 4 40

예λ₯Ό λ“€μ–΄, μ‹μž¬λ£Œ 1, 3, 5λ₯Ό μ„ νƒν•˜λ©΄ μ˜μ–‘λΆ„μ€ 100, 145, 130, 10으둜 쑰건을 λ§Œμ‘±ν•˜μ§€λ§Œ 가격은 270이 λœλ‹€. λŒ€μ‹  2, 3, 4λ₯Ό μ„ νƒν•˜λ©΄ μ˜μ–‘λΆ„μ˜ 합은 110, 130, 90, 10, λΉ„μš©μ€ 180이 λ˜λ―€λ‘œ, μ•žμ˜ λ°©λ²•λ³΄λ‹€λŠ” 더 λ‚˜μ€ 선택이 λœλ‹€.

μž…λ ₯으둜 μ‹μž¬λ£Œ ν‘œκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, μ΅œμ € μ˜μ–‘μ†Œ 기쀀을 λ§Œμ‘±ν•˜λŠ” μ΅œμ†Œ λΉ„μš©μ˜ μ‹μž¬λ£Œ 집합을 μ°Ύμ•„μ•Ό ν•œλ‹€.

 

문제 풀이

import sys
from itertools import combinations

n=int(sys.stdin.readline())
p,f,s,v=map(int, sys.stdin.readline().strip().split(' '))
nutri=[]
for _ in range(n):
    nutri.append(list(map(int, sys.stdin.readline().strip().split(' '))))

numbers=list(range(1,n+1))
min_cost=1e9
min_idx={}

for pick in range(1,n+1):
    pick_idx=list(combinations(numbers, pick))
    isAllPass=True
    for picked in pick_idx:
        mp, mf, ms, mv = 0, 0, 0, 0
        tmp_cost = 0
        for idx in picked:
            mp+=nutri[idx-1][0]
            mf+=nutri[idx-1][1]
            ms+=nutri[idx-1][2]
            mv+=nutri[idx-1][3]
            tmp_cost+=nutri[idx-1][4]
        if mp >= p and mf >= f and ms >= s and mv >= v:
            if min_cost >= tmp_cost:
                min_cost = tmp_cost
                if min_cost in min_idx.keys():
                    min_idx[min_cost].append(picked)
                else:
                    min_idx[min_cost]=[]
                    min_idx[min_cost].append(picked)
        else:
            isAllPass = False

    # λͺ¨λ“  인덱슀λ₯Ό λ½‘λŠ” 경우의 μˆ˜κ°€ 쑰건을 λ§Œμ‘±ν•  λ•Œ 더 큰 값은 탐색할 ν•„μš”μ—†μŒ
    if isAllPass:
        break

if min_cost==1e9:
    print(-1)
else:
    print(min_cost)
    min_idx[min_cost].sort()
    print(*min_idx[min_cost][0], sep=' ')
  • N이 μ΅œλŒ€ 15μ΄λ―€λ‘œ μ™„μ „ νƒμƒ‰μœΌλ‘œ 풀어도 μ‹œκ°„μ΄ˆκ³Όκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.
  • N개의 μ‹ν’ˆ 인덱슀 쀑 1λΆ€ν„° N개λ₯Ό λ½‘λŠ” 쑰합을 λͺ¨λ‘ νƒμƒ‰ν•˜λ©΄μ„œ ν•΄λ‹Ή μ‘°ν•©μœΌλ‘œ 쑰건을 λ§Œμ‘±ν•  수 μžˆλŠ”μ§€ ν™•μΈν•œλ‹€.
  • 쑰건을 λ§Œμ‘±ν•œλ‹€λ©΄ ν•΄λ‹Ή μ‘°ν•©μ˜ λΉ„μš©μ΄ 이전 κ³„μ‚°μ—μ„œ κ΅¬ν•œ μ΅œμ†Œ λΉ„μš©λ³΄λ‹€ μž‘κ±°λ‚˜ κ°™λ‹€λ©΄ μ΅œμ†Œ λΉ„μš©κ³Ό μ΅œμ†Œ λΉ„μš©μ„ κ΅¬μ„±ν•˜λŠ” μ‹ν’ˆ 인덱슀인 min_cost와 min_idxλ₯Ό μ—…λ°μ΄νŠΈν•œλ‹€.
  • 그리고 νŠΉμ • n개λ₯Ό 뽑을 λ•Œ, λͺ¨λ“  쑰합이 쑰건을 λ§Œμ‘±ν•œλ‹€λ©΄ κ·Έ μ΄μƒμ˜ 수λ₯Ό λ½‘λŠ” 것 λ˜ν•œ λͺ¨λ‘ λ§Œμ‘±ν•œλ‹€λŠ” λœ»μ΄λ―€λ‘œ 뽑을 개수 n개λ₯Ό 더 이상 νƒμƒ‰ν•˜μ§€ μ•Šκ³  for문을 λΉ μ Έλ‚˜μ˜¨λ‹€.
  • μ΅œμ†Œ λΉ„μš©μ„ κ΅¬μ„±ν•˜λŠ” μ‹ν’ˆ 인덱슀λ₯Ό κ΅¬ν•˜λŠ” κ³Όμ •μ—μ„œ μ£Όμ˜ν•  점은 ν•΄λ‹Ήν•˜λŠ” μ‹ν’ˆ μΈλ±μŠ€κ°€ μ—¬λŸ¬ 개일 경우 μ‚¬μ „μˆœμœΌλ‘œ κ°€μž₯ μ•žμ„œλŠ” μ‹ν’ˆ 인덱슀λ₯Ό 좜λ ₯ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— 각 μ΅œμ†Œ λΉ„μš©μ— λŒ€ν•œ μ‹ν’ˆ 인덱슀λ₯Ό λ”•μ…”λ„ˆλ¦¬ ν˜•νƒœλ‘œ μ €μž₯해두고, μ΅œμ’…μ μœΌλ‘œ ꡬ해진 μ΅œμ†Œ λΉ„μš©μ— ν•΄λ‹Ήν•˜λŠ” μ‹ν’ˆ μΈλ±μŠ€λ“€μ„ μ •λ ¬ν•΄μ€€ 뒀에 κ°€μž₯ μ•žμ— μ˜€λŠ” μš”μ†Œλ₯Ό 좜λ ₯ν•΄μ€˜μ•Ό ν•œλ‹€.