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

39-Munbin-Lee #160

Merged
merged 1 commit into from
May 3, 2024
Merged

39-Munbin-Lee #160

merged 1 commit into from
May 3, 2024

Conversation

Munbin-Lee
Copy link
Member

๐Ÿ”— ๋ฌธ์ œ ๋งํฌ

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

image

์ž„๋ฌธ๋นˆ์„ ๊ฒ€์ƒ‰ํ•ด์„œ ๋‚˜์˜จ ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

โœ”๏ธ ์†Œ์š”๋œ ์‹œ๊ฐ„

1์‹œ๊ฐ„

โœจ ์ˆ˜๋„ ์ฝ”๋“œ

๋ฌธ์ œ ์„ค๋ช…

image

์˜ˆ์ œ ์ž…์ถœ๋ ฅ์„ ๋จผ์ € ๋ณด๋ฉด ๋นจ๋ฆฌ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.


์žฌ๋ฃŒ์˜ ์ด๋ฆ„์€ ์•ŒํŒŒ๋ฒณ์ด๋ฏ€๋กœ, ์„ ํƒ์ง€๊ฐ€ ํ•˜๋‚˜๋ฐ–์— ์—†๋‹ค. dict๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅํ•œ๋‹ค.

prices = {}

for _ in range(N):
    item, price = input().split()
    prices[item] = int(price)

๋ ˆ์‹œํ”ผ๋Š” 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ๊ฐ ๋ ˆ์‹œํ”ผ๋ฅผ ๋ฆฌ์ŠคํŠธ์— ๊ทธ๋ƒฅ ์—ฐ๊ฒฐํ•˜์—ฌ ์ €์žฅํ•œ๋‹ค.

ex. [['LOVE', ['2WATER', '4HONEY', '2BEER']], ['BEER', ['1HOP', '3WATER', '1HOP']]]

  1. defaultdict๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ๋ฌผ์•ฝ์— ํ•ด๋‹นํ•˜๋Š” ๋ ˆ์‹œํ”ผ๋“ค์„ ์ €์žฅํ•œ๋‹ค.

defaultdict['LOVE'] = [['2WATER', '4HONEY', '2BEER'], [...]]
defaultdict['BEER'] = [['1HOP', '3WATER', '1HOP'], [...]]

๋ฌธ์ œ๋ฅผ ํ’€๋‹ค๋ณด๋‹ˆ ๋”ฑํžˆ ํŠน์ • ๋ฌผ์•ฝ์— ํ•ด๋‹นํ•˜๋Š” ๋ ˆ์‹œํ”ผ๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์–ด 1๋ฒˆ ๋ฐฉ๋ฒ•์œผ๋กœ ์ €์žฅํ–ˆ๋‹ค.

์ด ๋ถ€๋ถ„์€ ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ๊ฑฐ์น  ์ˆ˜ ๋ฐ–์— ์—†์„ ๊ฒƒ ๊ฐ™๋‹ค.

for _ in range(M):
    target, formula = input().split('=')
    terms = formula.split('+')
    recipes.append([target, terms])

๊ฐ ๋ฌผ์•ฝ์˜ ๋น„์šฉ์„ ๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ง๊ด€์ ์ด๋‹ค.

๋ ˆ์‹œํ”ผ์— ์žˆ๋Š” ๊ฐ ์žฌ๋ฃŒ์˜ ์ˆ˜ * ๊ฐ ์žฌ๋ฃŒ์˜ ๋น„์šฉ์„ ๋”ํ•˜๋ฉด ๋œ๋‹ค.

def updatePrice(target, terms):
    price = 0
    
    for term in terms:
        count = int(term[0])
        item = term[1:]
        
        if item not in prices:
            return
        
        price += count * prices[item]
    
    if target not in prices or prices[target] > price:
        prices[target] = price

๊ทธ๋Ÿฌ๋‚˜ ํ•œ ๊ฐ€์ง€ ๊ณ ๋ คํ•ด์•ผ ํ•  ์ ์ด ์žˆ๋‹ค.

๋ฌผ์•ฝ์˜ ์žฌ๋ฃŒ๋กœ ๋‹ค๋ฅธ ๋ฌผ์•ฝ์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ์ด๋‹ค.

1๋ฒˆ ์˜ˆ์ œ๋ฅผ ๋ณด๋ฉด LOVE์˜ ์žฌ๋ฃŒ์— BEER์ด ์žˆ๋‹ค.

๋งŒ์•ฝ ์ฒ˜์Œ ๋ ˆ์‹œํ”ผ๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ updatePrice()๋ฅผ ํ•œ๋‹ค๋ฉด,

updatePrice('BEER')์˜ ์‹œ์ ์€ updatePrice('LOVE') ์ดํ›„์ด๊ธฐ ๋•Œ๋ฌธ์—

LOVE์˜ ๋น„์šฉ์„ ๊ตฌํ•  ์ˆ˜ ์—†๋‹ค.

๊ทธ๋ž˜์„œ ์œ„์ƒ์ •๋ ฌ์ฒ˜๋Ÿผ ์ˆœ์„œ๋ฅผ ์ •ํ•ด์„œ ๊ตฌํ•ด์•ผํ•˜๋‚˜? ์ƒ๊ฐํ•˜๋‹ค๊ฐ€ ์ƒํ˜ธ ์ฐธ์กฐ ๋“ฑ ๋ณต์žกํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•˜์˜€๋‹ค.


๋ ˆ์‹œํ”ผ์˜ ๊ฐœ์ˆ˜๋Š” ๊ณ ์ž‘ 50๊ฐœ์ด๋‹ค.

๋”ฐ๋ผ์„œ ๋ชจ๋“  ๋ ˆ์‹œํ”ผ๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ updatePrice()๋ฅผ ํ•œ๋‹ค.

๋งŒ์•ฝ 1๊ฐœ๋ผ๋„ ํŠน์ • ์žฌ๋ฃŒ์˜ ๋น„์šฉ์ด ์—…๋ฐ์ดํŠธ(์ƒˆ๋กœ ์ƒ๊ธฐ๊ฑฐ๋‚˜, ์ด์ „๋ณด๋‹ค ์‹ธ์กŒ๊ฑฐ๋‚˜)๋˜์—ˆ๋‹ค๋ฉด

๋‹ค์‹œ 50๊ฐœ๋ฅผ ๋ชจ๋‘ ์ˆœํšŒํ•œ๋‹ค.

์ด ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•œ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด updatePrice()์˜ ๋ฐ˜ํ™˜๊ฐ’์„ bool๋กœ ๋ณ€๊ฒฝํ•˜์˜€๋‹ค.

def updatePrice(target, terms):
    price = 0
    
    for term in terms:
        count = int(term[0])
        item = term[1:]
        
        if item not in prices:
            return False
        
        price += count * prices[item]
    
    if target in prices and prices[target] <= price:
        return False
    
    prices[target] = price
    return True

๊ทธ๋ฆฌ๊ณ , ๋ฃจํ”„ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ณ€์ˆ˜ loop๋ฅผ or ์—ฐ์‚ฐํ•˜์—ฌ ํ•œ ๋ฒˆ์ด๋ผ๋„ ์—…๋ฐ์ดํŠธ๋˜๋ฉด, ์ „์ฒด ๋ ˆ์‹œํ”ผ๋ฅผ ๋‹ค์‹œ ์ˆœํšŒํ•œ๋‹ค.

loop = True

while loop:
    loop = False
    
    for recipe in recipes:
        loop |= updatePrice(recipe[0], recipe[1])

ํ˜น์€ ์ด๋Ÿฐ ๋ฐฉ๋ฒ•๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

๊ฒฐ๊ณผ๊ฐ€ ์ •ํ•ด์ง€๊ธฐ ์ „๊นŒ์ง€, ๊ฐ ๋ฃจํ”„๋ฅผ ๋Œ ๋•Œ๋งˆ๋‹ค ์ตœ์†Œ 1๊ฐœ์˜ ๋ฌผ์•ฝ์˜ ๋น„์šฉ์€ ์—…๋ฐ์ดํŠธ๋œ๋‹ค.

๋”ฐ๋ผ์„œ, ๋ ˆ์‹œํ”ผ์˜ ๊ฐฏ์ˆ˜๋งŒํผ ๋ฃจํ”„๋ฅผ ๊ทธ๋ƒฅ ๋Œ๋ฉด ๋œ๋‹ค.

์œ„์˜ ๋ฐฉ๋ฒ•๋ณด๋‹ค ์•„์ฃผ ์•„์ฃผ ์•„์ฃผ ์‚ด์ง ๋น„ํšจ์œจ์ ์ด๋‹ค.

for _ in range(M):
    for recipe in recipes:
        updatePrice(recipe[0], recipe[1])

๊ทธ๋ฆฌ๊ณ  ์ด๊ฑด ์ƒ๊ฐ๋งŒ ํ•ด๋ณธ ๋ฐฉ๋ฒ•์ธ๋ฐ, ๋ ˆ์‹œํ”ผ๋ฅผ ํŒŒ์‹ฑํ•  ๋•Œ์— ์žฌ๋ฃŒ์˜ ์‚ฌ์šฉ์ฒ˜๋ฅผ ์ €์žฅํ•œ๋‹ค.

1๋ฒˆ ์˜ˆ์ œ๋ฅผ ์˜ˆ๋กœ ๋“ค๋ฉด,

references['WATER'] = ['LOVE', 'BEER']
references['HONEY'] = ['LOVE']
references['BEER'] = ['LOVE']
references['HOP'] = ['BEER']

์ด๋ ‡๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ๊ฐ ๋น„์šฉ์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งˆ๋‹ค ๊ทธ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ dict์— ์ €์žฅํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ทธ dict๋ฅผ ๋‹ค์‹œ ์ˆœํšŒํ•˜๊ณ , ๊ทธ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋‹ค๋ฅธ dict์— ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๋ฐ˜๋ณตํ•œ๋‹ค.

์ด๋ก ์ƒ ๊ฐ€์žฅ ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ ๊ตฌํ˜„ํ•˜๊ธฐ ๊นŒ๋‹ค๋กญ๋‹ค.

๋ฌด์—‡๋ณด๋‹ค๋„ worst case์—์„œ๋Š” ํšจ๊ณผ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ตณ์ด ๊ตฌํ˜„ํ•ด๋ณด์ง€๋Š” ์•Š์•˜๋‹ค.

๐Ÿ“š ์ „์ฒด ์ฝ”๋“œ

stdin = open(0)

def input():
    return stdin.readline().rstrip()

N, M = map(int, input().split())

prices = {}

for _ in range(N):
    item, price = input().split()
    prices[item] = int(price)

recipes = []

for _ in range(M):
    target, formula = input().split('=')
    terms = formula.split('+')
    recipes.append([target, terms])

def updatePrice(target, terms):
    price = 0
    
    for term in terms:
        count = int(term[0])
        item = term[1:]
        
        if item not in prices:
            return False
        
        price += count * prices[item]
    
    if target in prices and prices[target] <= price:
        return False
    
    prices[target] = price
    return True

loop = True

while loop:
    loop = False
    
    for recipe in recipes:
        loop |= updatePrice(recipe[0], recipe[1])

if 'LOVE' not in prices:
    print('-1')
    exit()

answer = min(prices['LOVE'], 1000000001)
print(answer)

@Hwangyerin
Copy link

์ž„๋ฌธ๋นˆ์€ ์ด๋ฆ„์ด LOVE์ธ ๋งˆ๋ฒ•์˜ ๋ฌผ์•ฝ์„ ๋งŒ๋“ค๋ ค๊ณ  ํ•œ๋‹ค. (์ด ๋ฌผ์•ฝ์„ ๋จน์œผ๋ฉด ์ž„๋ฌธ๋นˆ์„ ์‚ฌ๋ž‘ํ•˜๊ฒŒ ๋œ๋‹ค) ์‹œ์žฅ์—์„œ ํŒŒ๋Š” ์žฌ๋ฃŒ์™€ ๊ทธ ๊ฐ€๊ฒฉ์ด ์ฃผ์–ด์ง€๊ณ , ์ž„๋ฌธ๋นˆ์ด ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋ฌผ์•ฝ์˜ ์‹์ด ์ฃผ์–ด์ง„๋‹ค. ์ด๋•Œ, LOVE๋ฅผ 1๋งŒํผ ๋งŒ๋“œ๋Š”๋ฐ ๋“œ๋Š” ๋น„์šฉ์˜ ์ตœ์†Ÿ๊ฐ’์„ ์ถœ๋ ฅํ•œ๋‹ค.

๋ฐฑ์ค€์˜ ๊ณผํ•™์ž ์ž„๋ฌธ๋นˆ์”จ๋Š” ๊ด€์‹ฌ๋ถ„์•ผ๊ฐ€ ์‚ฌ๋ž‘์ด๊ตฐ์š”. ์•„๋‹ˆ๋ฉด ๋ฐฑ์ค€์ด ์ž„๋ฌธ๋นˆ์”จ๋ฅผ ์–ด๋–ป๊ฒŒ๋“  ์‚ฌ๋ž‘ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š”๊ฑด๊ฐ€.?๐Ÿค”

Copy link
Member

@tgyuuAn tgyuuAn left a comment

Choose a reason for hiding this comment

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

import sys
from collections import defaultdict

MAX = 1000000001

def input(): return sys.stdin.readline().rstrip()

N, M = map(int, input().split())

cost = defaultdict(lambda : int(1e9))
receipes = defaultdict(list)
for _ in range(N):
    ingredient, ingredient_cost = input().split()
    cost[ingredient] = int(ingredient_cost)

for _ in range(M):
    result, receipe = input().split("=")
    ingredients = receipe.split("+")
    
    receipes[result].append(list((int(ingredient[0]), ingredient[1:]) for ingredient in ingredients))

def find_the_cheapest_cost(ingredient, receipes, cost, parent, cache):

    # ๋ ˆ์‹œํ”ผ๋„ ์—†๊ณ  ์‚ด ์ˆ˜๋„ ์—†์„ ๊ฒฝ์šฐ -1์„ ๋ฐ˜ํ™˜
    if len(receipes[ingredient]) == 0 and cost[ingredient] == int(1e9): return -1
    
    # ์ œ์กฐํ•  ์ˆ˜ ์—†์„ ๊ฒฝ์šฐ ์‚ด ์ˆ˜ ๋ฐ–์— ์—†์Œ
    if len(receipes[ingredient]) == 0: return cost[ingredient]

    parent.add(ingredient)

    for love_receipe in receipes[ingredient]:
        
        accumulate = 0
        flag = False
        for (count, sub_ingredient) in love_receipe:
            
            # ๋งŒ์•ฝ, ๋‚ด๋ถ€ ์žฌ๋ฃŒ์— ๋ถ€๋ชจ ์žฌ๋ฃŒ๊ฐ€ ๋“ค์–ด๊ฐˆ ๊ฒฝ์šฐ, ์‚ฌ์ดํด์„ ๋งŒ๋“œ๋ฏ€๋กœ ์žฌ์กฐ๋ฅผ ๊ทธ๋งŒ ๋‘ 
            if sub_ingredient in parent: 
                flag = True
                break
                
            sub_ingredient_cost = min(MAX,find_the_cheapest_cost(sub_ingredient, receipes, cost, parent, cache))
            
            # ๋‚ด๋ถ€ ์žฌ๋ฃŒ๋ฅผ ์‚ฌ์ง€๋„, ๋งŒ๋“ค์ง€๋„ ๋ชปํ•  ๊ฒฝ์šฐ ์ œ์กฐ๋ฅผ ๊ทธ๋งŒ ๋‘ 
            if sub_ingredient_cost == -1: 
                flag = True
                break
            
            if sub_ingredient_cost == MAX: accumulate = MAX
            else: accumulate += min(MAX,count * sub_ingredient_cost)
        
        # for๋ฌธ ์•ˆ์—์„œ break๋ฅผ ํƒ€์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ, ์ฆ‰ ๋‚ด๋ถ€ ์žฌ๋ฃŒ๋ฅผ ๋ชจ๋‘ ๊ตฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ
        else: 
            if cost[ingredient] == int(1e9) and accumulate > int(1e9): cost[ingredient] = MAX
            elif cost[ingredient] == -1: cost[ingredient] = accumulate
            else: cost[ingredient] = min(cost[ingredient], accumulate)
            
        # ๋งŒ์•ฝ ๋‚ด๋ถ€ ์žฌ๋ฃŒ์— ๋ถ€๋ชจ ์žฌ๋ฃŒ๊ฐ€ ๋“ค์–ด์žˆ์–ด์„œ ์žฌ์กฐ๋ฅผ ๋ชปํ•  ๊ฒฝ์šฐ -1์„ ๋ฐ˜ํ™˜ ํ•จ
        if flag and cost[ingredient] == int(1e9): cost[ingredient] = -1

    parent.discard(ingredient)
    
    return cost[ingredient]

print(find_the_cheapest_cost("LOVE", receipes, cost, {"LOVE"}, cache))

์ผ๋‹จ 1์‹œ๊ฐ„ ์งธ ์ด๊ธด ํ•œ๋ฐ,

์งˆ๋ฌธ ๊ฒŒ์‹œํŒ ๋ฐ˜๋ก€๋ฅผ ๋‹ค ํ†ต๊ณผํ•˜๋Š”๋ฐ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ๋‚˜๋„ค์š”.

LOVE๋ถ€ํ„ฐ ์žฌ๋ฃŒ๋ฅผ ํƒ€๊ณ ํƒ€๊ณ  ๊ฐ€๋ฉด์„œ ๊ณ„์† ์ตœ์†Œ ๊ฐ’์„ ์ฐพ์•„๋‚˜๊ฐ€๋Š” ๋กœ์ง์ธ๋ฐ,







๋ฌธ๋นˆ๋‹˜์ด ๋งํ•˜์…จ๋˜ ๋ฐฉ๋ฒ•์ด๋„ค์š”.

image







๊ทผ๋ฐ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์™œ ๋‚˜๋Š”๊ฑด์ง€ ใ… ใ… ใ… ใ… ใ… ใ… ใ… ใ… ใ… ใ… ใ… ใ… ใ… 







๋ฌธ๋นˆ๋‹˜ ํ’€์ด ๋ณด๋ฉด์„œ ๋‹ค์‹œ ํ’€์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค....... ํ™”๊ฐ€ ๋‚˜๋„ค์š” ๐Ÿ˜ ๐Ÿ˜ ๐Ÿ˜ 


๋ฌธ๋นˆ๋‹˜ ํ’€์ด ๊ต‰์žฅํžˆ ์ง๊ด€์ ์ด๊ณ  ์ œ ํ’€์ด๋ณด๋‹ค ํ›จ์”ฌํ›จ์”ฌํ›จ์”ฌ ์‰ฝ๋„ค์š”.

ํก์ˆ˜ํ–ˆ์”๋‹ˆ๋‹ค.

import sys
from collections import defaultdict

def input(): return sys.stdin.readline().rstrip()

N, M = map(int, input().split())

cost = defaultdict(lambda : int(1e9))
receipes = defaultdict(list)
for _ in range(N):
    ingredient, ingredient_cost = input().split()
    cost[ingredient] = int(ingredient_cost)

for _ in range(M):
    result, receipe = input().split("=")
    ingredients = receipe.split("+")
    
    receipes[result].append(list((int(ingredient[0]), ingredient[1:]) for ingredient in ingredients))

def update_price(target, receipes, cost):
    loop_flag = False
    
    for receipe in receipes:
        
        accumulate = 0
        for (count, ingredient) in receipe:

            if ingredient not in cost: break
            
            accumulate += (count * cost[ingredient])
        
        else:
            if target not in cost or accumulate < cost[target]:
                loop_flag = True
                cost[target] = accumulate

    return loop_flag

loop_flag = True

while loop_flag:
    loop_flag = False
    
    for target in receipes:
        loop_flag |= update_price(target, receipes[target], cost)

print(min(1000000001,cost["LOVE"])) if "LOVE" in cost else print("-1")

@pknujsp
Copy link
Collaborator

pknujsp commented Mar 30, 2024

์š” ๋ฌธ์ œ ๋ฉฐ์น ๋™์•ˆ ํ‹ˆํ‹ˆ์ด ํŒ ๋Š”๋ฐ ๊ฒฐ๊ตญ ๊ธฐ๋ณธ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋„ ๋ชป ๋งž์ถ”๊ฒ ์–ด์„œ
๋ฌธ๋นˆ๋‹˜ ํ’€์ด ๋ณด๊ณ  ๊ณต๋ถ€ํ•œ ๋’ค์— ๋‹ค์‹œ ํ’€์–ด๋ด์•ผ ๊ฒ ๋„ค์š”

๋„ˆ๋ฌด ์–ด๋ ต๋„ค์š” ์ด๊ฑฐ

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.

5 participants