Problem Solving/[ν•­ν•΄99] TIL

99클럽 μ½”ν…Œ μŠ€ν„°λ”” 25일차 TIL / 완전탐색

geum 2024. 11. 21. 21:56

✏️ 문제

[λ°±μ€€/BOJ] 2116번: μ£Όμ‚¬μœ„ μŒ“κΈ°(https://www.acmicpc.net/problem/2116)

 

μ²œμˆ˜λŠ” μ—¬λŸ¬ μ’…λ₯˜μ˜ μ£Όμ‚¬μœ„λ₯Ό 가지고 μŒ“κΈ° 놀이λ₯Ό ν•˜κ³  μžˆλ‹€. μ£Όμ‚¬μœ„μ˜ λͺ¨μ–‘은 λͺ¨λ‘ 크기가 같은 μ •μœ‘λ©΄μ²΄μ΄λ©° 각 λ©΄μ—λŠ” 1λΆ€ν„° 6κΉŒμ§€μ˜ μˆ«μžκ°€ ν•˜λ‚˜μ”© μ ν˜€μžˆλ‹€. κ·ΈλŸ¬λ‚˜ 보톡 μ£Όμ‚¬μœ„μ²˜λŸΌ 마주 λ³΄λŠ” 면에 μ ν˜€μ§„ 숫자의 합이 λ°˜λ“œμ‹œ 7이 λ˜λŠ” 것은 μ•„λ‹ˆλ‹€.

μ£Όμ‚¬μœ„ μŒ“κΈ° λ†€μ΄λŠ” μ•„λž˜μ—μ„œλΆ€ν„° 1번 μ£Όμ‚¬μœ„, 2번 μ£Όμ‚¬μœ„, 3번 μ£Όμ‚¬μœ„, … 의 μˆœμ„œλ‘œ μŒ“λŠ” 것이닀. μŒ“μ„ λ•Œ λ‹€μŒκ³Ό 같은 κ·œμΉ™μ„ μ§€μΌœμ•Ό ν•œλ‹€: μ„œλ‘œ λΆ™μ–΄ μžˆλŠ” 두 개의 μ£Όμ‚¬μœ„μ—μ„œ μ•„λž˜μ— μžˆλŠ” μ£Όμ‚¬μœ„μ˜ μœ—λ©΄μ— μ ν˜€μžˆλŠ” μˆ«μžλŠ” μœ„μ— μžˆλŠ” μ£Όμ‚¬μœ„μ˜ μ•„λž«λ©΄μ— μ ν˜€μžˆλŠ” μˆ«μžμ™€ κ°™μ•„μ•Ό ν•œλ‹€. λ‹€μ‹œ λ§ν•΄μ„œ, 1번 μ£Όμ‚¬μœ„ μœ—λ©΄μ˜ μˆ«μžλŠ” 2번 μ£Όμ‚¬μœ„ μ•„λž«λ©΄μ˜ μˆ«μžμ™€ κ°™κ³ , 2번 μ£Όμ‚¬μœ„ μœ—λ©΄μ˜ μˆ«μžλŠ” 3번 μ£Όμ‚¬μœ„ μ•„λž«λ©΄μ˜ μˆ«μžμ™€ κ°™μ•„μ•Ό ν•œλ‹€. 단, 1번 μ£Όμ‚¬μœ„λŠ” λ§ˆμŒλŒ€λ‘œ 놓을 수 μžˆλ‹€.

μ΄λ ‡κ²Œ μŒ“μ•„ λ†“μœΌλ©΄ κΈ΄ 사각 κΈ°λ‘₯이 λœλ‹€. 이 사각 κΈ°λ‘₯μ—λŠ” 4개의 κΈ΄ μ˜†λ©΄μ΄ μžˆλ‹€. 이 4개의 μ˜†λ©΄ μ€‘μ—μ„œ μ–΄λŠ ν•œ 면의 숫자의 합이 μ΅œλŒ€κ°€ λ˜λ„λ‘ μ£Όμ‚¬μœ„λ₯Ό μŒ“κ³ μž ν•œλ‹€. μ΄λ ‡κ²Œ ν•˜κΈ° μœ„ν•˜μ—¬ 각 μ£Όμ‚¬μœ„λ₯Ό μœ„ μ•„λž˜λ₯Ό κ³ μ •ν•œ 채 μ˜†μœΌλ‘œ 90도, 180도, λ˜λŠ” 270도 돌릴 수 μžˆλ‹€. ν•œ μ˜†λ©΄μ˜ 숫자의 ν•©μ˜ μ΅œλŒ“κ°’μ„ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

 

πŸ€– μž…μΆœλ ₯ μ˜ˆμ‹œ

 

🧐 λ‚œμ΄λ„/μ†Œμš” μ‹œκ°„

βœ… λ‚œμ΄λ„: solved.ac κΈ°μ€€ G5

βœ… μ†Œμš” μ‹œκ°„: 1μ‹œκ°„ 30λΆ„ 초과

βœ… ꢌμž₯ μ‹œκ°„: 1μ‹œκ°„ 30λΆ„

 

πŸ’‘ 풀이

1) 문제 이해

μ—¬λŸ¬ 개의 μ£Όμ‚¬μœ„λ₯Ό μŒ“μ•„μ„œ μ˜†λ©΄μ— 적힌 숫자의 ν•© 쀑 μ΅œλŒ“κ°’μ„ κ΅¬ν•˜λŠ” λ¬Έμ œλ‹€. λ„€ μ˜†λ©΄μ˜ 합을 λ‹€ ꡬ할 ν•„μš”λŠ” μ—†κ³  λ„€ λ©΄ 쀑 κ°€μž₯ 큰 값을 κΈ°μ€€μœΌλ‘œ 맀 μ£Όμ‚¬μœ„λ§ˆλ‹€ μ˜†λ©΄ 쀑 μ΅œλŒ“κ°’μ„ λˆ„μ μœΌλ‘œ 더해주면 λœλ‹€.

 

λ¬Έμ œμ—μ„œ '1번 μ£Όμ‚¬μœ„λŠ” λ§ˆμŒλŒ€λ‘œ 놓을 수 μžˆλ‹€'λŠ” 쑰건을 μ€¬λŠ”λ° 이걸 잘 ν™œμš©ν•΄μ•Ό ν•œλ‹€.

 

2) 아이디어 흐름 및 μ½”λ“œ

β‘  μ§ 인덱슀 리슀트 μ •μ˜

pair_idx = [5, 3, 4, 1, 2, 0]

 

  • μ£Όμ‚¬μœ„λ₯Ό μ΄λ£¨λŠ” 값이 μž…λ ₯λ˜λŠ” μˆœμ„œλŠ” μ „κ°œλ„λ₯Ό κΈ°μ€€μœΌλ‘œ A, B, C, D, E, F이고 각 면은 A-F / B-D / C-E둜 짝지어진닀. 
  • A~F에 ν•΄λ‹Ήν•˜λŠ” κ°’μ˜ μΈλ±μŠ€λŠ” 0~5이닀.
  • pair_idx[i] = i번째 λ©΄κ³Ό λ§ˆμ£Όλ³΄λŠ” λ©΄
    • i=0은 A면을 μ˜λ―Έν•˜κ³  pair_idx[0]은 Aλ©΄κ³Ό λ§ˆμ£Όλ³΄λŠ” F면의 인덱슀 값이닀.

 

β‘‘ 1번 μ£Όμ‚¬μœ„ λ°°μΉ˜ν•˜κΈ°

for i in range(6):
    top, bottom = dice_list[0][pair_idx[i]], dice_list[0][i]
    
    # 1번 μ£Όμ‚¬μœ„ μ˜†λ©΄ μ΅œλŒ€κ°’
    max_side = max([num for num in dice_list[0] if num not in (top, bottom)])
    
    temp = max_side
    
    prev_top = top

 

  • for i in range(6)
    • 1번 μ£Όμ‚¬μœ„λŠ” λ§ˆμŒλŒ€λ‘œ 놓을 수 μžˆλ‹€κ³  ν–ˆκΈ° λ•Œλ¬Έμ— 6λ©΄ λͺ¨λ‘ λ°”λ‹₯에 닿도둝 λ‘˜ 수 μžˆλ‹€.
    • λ°”λ‹₯에 닿은 면이 λ°”λ€” λ•Œλ§ˆλ‹€ μŒ“μ€ μ£Όμ‚¬μœ„ μ˜†λ©΄μ˜ ν•© 쀑 μ΅œλŒ€λ₯Ό μ°ΎλŠ” 과정을 λ°˜λ³΅ν•΄μ•Ό ν•œλ‹€.
  • top, bottom = dice_list[0][pair_idx[i]], dice_list[0][i]
    • 1번 μ£Όμ‚¬μœ„μ˜ μœ—λ©΄κ³Ό 밑면을 λ°”κΏ” κ°€λ©΄μ„œ λ°°μΉ˜ν•˜λŠ” 과정을 μ²˜λ¦¬ν•˜λŠ” μ½”λ“œλ‹€.
  • max_side = max([num for num in dice_list[0] if num not in (top, bottom)])
    • μœ—λ©΄κ³Ό μ•„λž«λ©΄μ΄ 정해지면 μ˜†λ©΄λ„ μžμ—°μŠ€λŸ½κ²Œ μ •ν•΄μ§€κ²Œ λœλ‹€.
    • 1)μ—μ„œλ„ μ–ΈκΈ‰ν–ˆλ“―μ΄ μ˜†λ©΄ κ°’ 쀑 μ΅œλŒ“κ°’μ—λ§Œ 관심이 있기 λ•Œλ¬Έμ— max()λ₯Ό ν™œμš©ν–ˆλ‹€.
  • temp = max_side / prev_top = top
    • temp = max_side: 1번 μ£Όμ‚¬μœ„ λ°°μΉ˜κ°€ λ°”λ€” λ•Œλ§ˆλ‹€ 각 μ£Όμ‚¬μœ„μ˜ μ˜†λ©΄ μ΅œλŒ“κ°’μ„ 더해주기 μœ„ν•œ λ³€μˆ˜λ‘œ μ΄ˆκΈ°κ°’μ€ 1번 μ£Όμ‚¬μœ„μ˜ μ˜†λ©΄ 쀑 μ΅œλŒ“κ°’μ΄λ‹€.
    • prev_top = top: i번째 μ£Όμ‚¬μœ„μ˜ μœ—λ©΄μ— 적힌 μˆ«μžμ™€ i+1번째 μ£Όμ‚¬μœ„μ˜ 밑면에 적힌 μˆ«μžκ°€ κ°™μ•„μ•Ό ν•˜λŠ” 쑰건을 μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ 이전 μ£Όμ‚¬μœ„μ˜ μœ—λ©΄ κ°’ μ €μž₯ λͺ©μ μœΌλ‘œ μ‚¬μš©ν•œ λ³€μˆ˜λ‹€.

 

β‘’ 2번 μ£Όμ‚¬μœ„λΆ€ν„° μŒ“κΈ°

for j in range(1, len(dice_list)):
    current_bottom_idx = dice_list[j].index(prev_top)
    
    current_top = dice_list[j][pair_idx[current_bottom_idx]]
    
    temp += max([num for num in dice_list[j] if num not in (current_top, dice_list[j][current_bottom_idx])])
    
    prev_top = current_top

 

  • for j in range(1, len(dice_list)
    • 2번 μ£Όμ‚¬μœ„λΆ€ν„° μŒ“μ•„μ£ΌλŠ” 과정이닀.
  • current_bottom_idx = dice_list[j].index(prev_top)
    • i번째 μ£Όμ‚¬μœ„μ˜ 밑면에 적힌 μˆ«μžμ™€ 이제 μŒ“μ•„ μ˜¬λ €μ•Ό ν•˜λŠ” i+1번째 μ£Όμ‚¬μœ„μ˜ μœ—λ©΄μ— 적힌 μˆ«μžκ°€ κ°™μ•„μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— 이전에 κΈ°λ‘ν•΄λ‘μ—ˆλ˜ prev_top 값을 μ΄μš©ν•΄ A~Fλ©΄ 쀑 μ–΄λ–€ 면이 λ°‘μœΌλ‘œ 와야 ν•˜λŠ”μ§€ ν™•μΈν•œλ‹€.
  • current_top = dict_list[j][pair_idx[current_bottom_idx]]
    • ν˜„μž¬ λ°‘λ©΄κ³Ό λ§ˆμ£Όλ³΄λŠ” 면을 μ°ΎκΈ° μœ„ν•œ λΆ€λΆ„μœΌλ‘œ, 1번 μ£Όμ‚¬μœ„μ—μ„œ μ‚¬μš©ν•œ 둜직과 λ™μΌν•˜λ‹€.
  • prev_top = current_top
    • ν•œ μ£Όμ‚¬μœ„λ₯Ό μŒ“κ³  λ‚˜λ©΄ μœ—λ©΄μ˜ 값을 κ°€μž₯ 졜근 μ£Όμ‚¬μœ„μ˜ μœ—λ©΄ κ°’μœΌλ‘œ κ°±μ‹ ν•΄μ€€λ‹€.
    • 이 값을 κΈ°μ€€μœΌλ‘œ λ‹€μŒ μ£Όμ‚¬μœ„κ°€ μŒ“μ•„μ Έμ•Ό ν•œλ‹€.

 

3) 전체 μ½”λ“œ

import sys

input = sys.stdin.readline

N = int(input())

dice_list = [list(map(int, input().split())) for _ in range(N)]

answer = 0

pair_idx = [5, 3, 4, 1, 2, 0]

for i in range(6):
    top, bottom = dice_list[0][pair_idx[i]], dice_list[0][i]
    
    # 1번 μ£Όμ‚¬μœ„ μ˜†λ©΄ μ΅œλŒ€κ°’
    max_side = max([num for num in dice_list[0] if num not in (top, bottom)])
    
    temp = max_side
    
    prev_top = top
    
    # 2번 μ£Όμ‚¬μœ„λΆ€ν„° μŒ“κΈ°
    for j in range(1, len(dice_list)):
        current_bottom_idx = dice_list[j].index(prev_top)
        
        current_top = dice_list[j][pair_idx[current_bottom_idx]]
        
        temp += max([num for num in dice_list[j] if num not in (current_top, dice_list[j][current_bottom_idx])])
    
        prev_top = current_top
        
    answer = max(answer, temp)
    
print(answer)

 

4) μ–΄λ €μ› λ˜ 점/배운 점

🚨 μ–΄λ €μ› λ˜ 점

  • μ²˜μŒμ—λŠ” λ¬Έμ œμ— 주어진 그림만 보고 Aκ°€ 무쑰건 μœ—λ©΄, Fκ°€ 무쑰건 밑면이라고 μƒκ°ν•΄μ„œ κ΅¬ν˜„ 방법을 λ– μ˜¬λ¦¬λŠ” 데에 어렀움이 μžˆμ—ˆλ‹€.

❗ 배운 점

  • μ–΄λ €μ›Œλ³΄μ΄λŠ” 문제라고 겁먹지 말고 λ‘œμ§μ„ 잘 μ„Έμš°μž. 둜직만 κΉ”λ”ν•˜κ²Œ λ‚˜μ˜€λ©΄ κ·ΈλŒ€λ‘œ κ΅¬ν˜„ν•˜κΈ°λ§Œ ν•˜λ©΄ 됨 🀟