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

99클럽 μ½”ν…Œ μŠ€ν„°λ”” 26일차 TIL / μˆ˜ν•™&DP(λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°)

geum 2024. 11. 22. 19:19

✏️ 문제

[λ°±μ€€/BOJ] 9655번: 돌 κ²Œμž„(https://www.acmicpc.net/problem/9655)

 

돌 κ²Œμž„μ€ 두 λͺ…μ΄μ„œ μ¦κΈ°λŠ” μž¬λ°ŒλŠ” κ²Œμž„μ΄λ‹€.

νƒμž μœ„μ— 돌 Nκ°œκ°€ μžˆλ‹€. 상근이와 μ°½μ˜μ΄λŠ” 턴을 λ²ˆκ°ˆμ•„κ°€λ©΄μ„œ λŒμ„ κ°€μ Έκ°€λ©°, λŒμ€ 1개 λ˜λŠ” 3개 κ°€μ Έκ°ˆ 수 μžˆλ‹€. λ§ˆμ§€λ§‰ λŒμ„ κ°€μ Έκ°€λŠ” μ‚¬λžŒμ΄ κ²Œμž„μ„ 이기게 λœλ‹€.

두 μ‚¬λžŒμ΄ μ™„λ²½ν•˜κ²Œ κ²Œμž„μ„ ν–ˆμ„ λ•Œ, μ΄κΈ°λŠ” μ‚¬λžŒμ„ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€. κ²Œμž„μ€ 상근이가 λ¨Όμ € μ‹œμž‘ν•œλ‹€.

 

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

 

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

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

βœ… μ†Œμš” μ‹œκ°„: 5λΆ„

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

 

πŸ’‘ 풀이

1) 문제 이해

문제λ₯Ό 보자마자 λ°°μŠ€ν‚¨λΌλΉˆμŠ€ 31 κ²Œμž„μ΄ 생각났닀. μ € κ²Œμž„μ— ν•„μŠΉ κ·œμΉ™μ΄ μžˆλŠ” κ²ƒμ²˜λŸΌ 이 λ¬Έμ œλ„ λΆ„λͺ…νžˆ 상근이가 무쑰건 μ΄κΈ°κ±°λ‚˜ μ§€λŠ” κ·œμΉ™μ΄ μžˆμ„ 거라고 μƒκ°ν–ˆλ‹€.

 

λ‚˜λŠ” μˆ˜ν•™μ μΈ 방법(이라고 ν•˜κΈ°μ—λŠ” λ„ˆλ¬΄ κ°„λ‹¨ν•˜κΈ΄ ν•˜μ§€λ§Œ)으둜 ν’€μ–΄μ„œ λ§žμ•˜λŠ”λ° 문제 λΆ„λ₯˜μ— 'λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°'이 있길래 DPλ‘œλ„ ν’€μ–΄λ³΄μ•˜λ‹€.

 

2-1) μˆ˜ν•™ - 아이디어 흐름 및 μˆ˜ν•™μ  증λͺ…

β‘  N이 ν™€μˆ˜μΌ λ•Œ

λ¬Έμ œμ—μ„œ ν•œ λ²ˆμ— 가지고 갈 수 μžˆλŠ” λŒμ€ 1개 μ•„λ‹ˆλ©΄ 3개라고 ν–ˆκΈ° λ•Œλ¬Έμ— 전체 돌 κ°œμˆ˜κ°€ 1κ°œμ΄κ±°λ‚˜ 3개이면 무쑰건 상근이가 이기게 λœλ‹€.

 

μ—¬κΈ°μ„œ 값을 μ’€ 더 ν™•μž₯μ‹œν‚€λ©΄μ„œ 돌 κ°œμˆ˜κ°€ ν™€μˆ˜μΈ 경우λ₯Ό λ”°μ Έλ΄€λ‹€.

 

N = 5 → 상근 1, 창영 1, 상근 3(승) / 상근 1, 창영 3, 상근 1(승) / 상근 3, 창영 1, 상근 1(승)

N = 7 → 상근 1, 창영 1, 상근 1, 창영 1, 상근 3(승) / 상근 1, 창영 1, 상근 3, 창영 1, 상근 1(승) / ...

 

N이 ν™€μˆ˜λ©΄ μ–΄λ–»κ²Œ 해도 상근이가 이기게 λ˜λŠ” 것을 μ•Œ 수 μžˆλ‹€.

 

β‘‘ N이 짝수일 λ•Œ

N이 2일 λ•Œ 상근 1, 창영 1둜 μ°½μ˜μ΄κ°€ 이기게 λœλ‹€.

 

β‘ μ—μ„œμ™€ λ™μΌν•˜κ²Œ N이 2 초과 짝수인 κ²½μš°μ— λŒ€ν•΄ ν™•μΈν•΄λ³΄μž.

 

N = 4 → 상근 1, 창영 1, 상근 1, 창영 1(패) / 상근 1, 창영 3(패) / 상근 3, 창영 1(패)

 

N이 6일 λ•ŒλŠ” 적지 μ•Šμ•„λ„ μ°½μ˜μ΄κ°€ μ΄κΈ°λŠ” 게 λͺ…λ°±ν•˜λ‹€.

 

β‘’ μˆ˜ν•™μ  증λͺ…

μœ„μ˜ μ ‘κ·Ό 방식은 'μ΄λ ‡κ²Œ ν•˜λ‹ˆκΉŒ λ˜λ”λΌ' 식에 κ°€κΉŒμš΄ 것 κ°™μ•„ μ±—μ§€ν”Όν‹°μ˜ 도움을 λ°›μ•„ μˆ˜ν•™μ μœΌλ‘œ μ–΄λ–»κ²Œ 증λͺ…ν•  수 μžˆλŠ”μ§€ 확인해봀닀.


 

< 귀납법 적용 >

 

κ°€μ„€: N이 ν™€μˆ˜λ©΄ 상근이가 이기고 짝수면 μ°½μ˜μ΄κ°€ 이긴닀.

  •  κ·€λ‚© κ°€μ •(N=k일 λ•Œ)
    • kκ°€ ν™€μˆ˜λ©΄ 상근이가 이긴닀.
    • kκ°€ 짝수면 μ°½μ˜μ΄κ°€ 이긴닀.
  • κ·€λ‚© 증λͺ…(N=k+1일 λ•Œ)
    • k+1이 ν™€μˆ˜λ©΄?
      1. 상근이가 1개λ₯Ό κ°€μ Έκ°ˆ 경우 N=kκ°€ 되고 kλŠ” 짝수 → μ°½μ˜μ΄λŠ” 항상 ν™€μˆ˜ 개의 돌(k-1 λ˜λŠ” k-3)을 μƒκ·Όμ΄μ—κ²Œ λ„˜κΈ°κ²Œ λœλ‹€.
      2. 상근이가 3개λ₯Ό κ°€μ Έκ°ˆ 경우 N=k-2κ°€ 되고  k+1이 ν™€μˆ˜κΈ° λ•Œλ¬Έμ— k-2λŠ” 짝수 → 이 κ²½μš°μ—λ„ μ°½μ˜μ΄λŠ” 항상 ν™€μˆ˜ 개의 돌(k-3 λ˜λŠ” k-5)λ₯Ό μƒκ·Όμ΄μ—κ²Œ λ„˜κΈ°κ²Œ λœλ‹€.
      3. ν™€μˆ˜ 개의 돌이 남은 μƒνƒœμ—μ„œ μƒκ·Όμ΄μ˜ 턴이 λŒμ•„μ˜€λ©΄ μƒκ·Όμ΄λŠ” ν™€μˆ˜ 개λ₯Ό μ „λΆ€ 가지고 였면 되기 λ•Œλ¬Έμ— 무쑰건 이기게 λœλ‹€.
    • k+1이 짝수면?
      1. k+1이 ν™€μˆ˜μΈ κ²½μš°μ™€ λ™μΌν•œ 둜직으둜 λ™μž‘ν•΄ μ°½μ˜μ΄κ°€ 무쑰건 이기게 λœλ‹€.

 

2-2) μˆ˜ν•™ - 전체 μ½”λ“œ

N = int(input())

if N%2 != 0:
    print("SK")
else:
    print("CY")

 

3-1) DP - 아이디어 흐름 및 μ½”λ“œ

β‘  DP ν…Œμ΄λΈ” μ •μ˜ 및 μ΄ˆκΈ°κ°’ μ±„μš°κΈ°

개인적으둜 DP μœ ν˜•μ„ ν’€ λ•Œ κ°€μž₯ μ€‘μš”ν•œ 뢀뢄은 DP ν…Œμ΄λΈ”μ„ μ •μ˜ν•˜λŠ” 것이라고 μƒκ°ν•œλ‹€. DP ν…Œμ΄λΈ”μ„ μ μ ˆν•œ κ°’μœΌλ‘œ μ±„μšΈ 수 μžˆμ–΄μ•Ό 이걸 ν™œμš©ν•΄μ„œ 문제λ₯Ό ν’€ 수 있기 λ•Œλ¬Έμ—..! ν•˜μ§€λ§Œ 이 λ¬Έμ œλŠ” μ„€λͺ…도 ꡉμž₯히 짧고, DPλ₯Ό 쓰지 μ•Šμ•„λ„ ν’€ 수 μžˆλŠ” 방법이 μžˆμ–΄μ„œ κ·ΈλŸ°κ°€ DP ν…Œμ΄λΈ”μ„ μ–΄λ–»κ²Œ ꡬ성해야 할지 도무지 감이 μ˜€μ§€ μ•Šμ•˜λ‹€.

 

λ°±μ€€ 질문 κ²Œμ‹œνŒμ„ λ‘˜λŸ¬λ³΄λŠ”λ° '이 λ¬Έμ œκ°€ μ™œ DP인지 λͺ¨λ₯΄κ² λ‹€'λŠ” μœ μ €κ°€ λͺ‡ λΆ„ μžˆμ—ˆκ³  힌트λ₯Ό μ£ΌλŠ” 뢄이 μžˆμ–΄μ„œ κ·Έ λ‚΄μš©μ„ μ°Έκ³ ν–ˆλ‹€.

 

1개 이상 k개 μ΄ν•˜μ˜ λŒμ„ κ°€μ Έκ°€λŠ” κ²Œμž„μ΄ μžˆλ‹€κ³  ν•  λ•Œ,
일반적으둜 κ²Œμž„ μ΄λ‘ μ—μ„œμ˜ DP ν…Œμ΄λΈ”μ€ μ•„λž˜μ™€ 같이 μ •μ˜ν•  수 μžˆλ‹€.

DP[i] = i번째 돌이 λ‚¨μ•˜μ„ λ•Œ, 선곡 ν”Œλ ˆμ΄μ–΄κ°€ μŠΉλ¦¬ν•  수 μžˆλŠ”κ°€?

좜처: https://www.acmicpc.net/board/view/151649

 

dp = [0]*1001

# dp[i]: 돌이 i개 남아 μžˆμ„ λ•Œ 상근이가 이길 수 μžˆλŠ”μ§€ 체크
dp[1], dp[2], dp[3] = True, False, True

 

μœ„ λ‚΄μš©μ΄ ꡉμž₯히 큰 νžŒνŠΈμ˜€κΈ° λ•Œλ¬Έμ— μ €κ±Έ λ°”νƒ•μœΌλ‘œ booleanν˜•μ˜ DP ν…Œμ΄λΈ”μ„ μ •μ˜ν–ˆλ‹€.

 

β‘‘ 점화식 μœ λ„

for i in range(4, 1001):
    if not dp[i-1] or not dp[i-3]:
        dp[i] = True

 

  • if not dp[i-1] or not dp[i-3]
    • 돌이 i개 λ‚¨μ•˜μ„ λ•Œ 상근이가 이기렀면 돌이 i-1개 λ‚¨μ•˜μ„ λ•Œλ‚˜ i-3개 λ‚¨μ•˜μ„ λ•Œ 상근이가 이길 수 μ—†λŠ” 상황이면 λœλ‹€.
    • i=5라고 κ°€μ •
      1. 돌이 4개(i-1) λ‚¨μ•˜μ„ λ•Œλ‚˜ 돌이 2개(i-3) λ‚¨μ•˜μ„ λ•Œ λ§ˆμ§€λ§‰ λŒμ„ μ°½μ˜μ΄κ°€ κ°€μ Έκ°€λ©΄ i=5일 λ•Œ μƒκ·Όμ΄λŠ” 무쑰건 이길 수 μžˆλ‹€.

 

3-2) DP - 전체 μ½”λ“œ

N = int(input())

dp = [0]*1001

# dp[i]: 돌이 i개 남아 μžˆμ„ λ•Œ 상근이가 이길 수 μžˆλŠ”μ§€ 체크
dp[1], dp[2], dp[3] = True, False, True

for i in range(4, 1001):
    if not dp[i-1] or not dp[i-3]:
        dp[i] = True

if dp[N]:
    print("SK")
else:
    print("CY")

 

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

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

  • λ¬Έμ œλŠ” 금방 ν’€μ—ˆμ§€λ§Œ DPλ₯Ό μ–΄λ–»κ²Œ μ μš©ν•  수 μžˆμ„μ§€ μƒκ°ν•΄λ‚΄λŠ” 게 μ–΄λ €μ› λ‹€.

❗ 배운 점

  • DP ν…Œμ΄λΈ”μ˜ 값이 무쑰건 숫자일 ν•„μš”κ°€ μ—†λ‹€. 상황에 맞게 적절히 μ„€μ •ν•˜λ©΄ λ˜λŠ”λ° 이건 μ—°μŠ΅μ„ 많이 해봐야 λ°”λ‘œ μΊμΉ˜ν•  수 μžˆμ„ 것 κ°™λ‹€.