λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
⭐ Problem_Solving/λ°±μ€€

[λ°±μ€€] 20057 λ§ˆλ²•μ‚¬ 상어와 토넀이도 (Python/파이썬)

by ν¬μŠ€νŠΈμ‰μ΄ν¬ 2022. 10. 4.

<문제 링크>

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

 

20056번: λ§ˆλ²•μ‚¬ 상어와 νŒŒμ΄μ–΄λ³Ό

첫째 쀄에 N, M, Kκ°€ 주어진닀. λ‘˜μ§Έ 쀄뢀터 M개의 쀄에 νŒŒμ΄μ–΄λ³Όμ˜ 정보가 ν•œ 쀄에 ν•˜λ‚˜μ”© 주어진닀. νŒŒμ΄μ–΄λ³Όμ˜ μ •λ³΄λŠ” λ‹€μ„― μ •μˆ˜ ri, ci, mi, si, di둜 이루어져 μžˆλ‹€. μ„œλ‘œ λ‹€λ₯Έ 두 νŒŒμ΄μ–΄λ³Όμ˜ μœ„μΉ˜

www.acmicpc.net

<풀이 μ „λž΅>

  1. νŠΉλ³„ν•œ μ•Œκ³ λ¦¬μ¦˜μ„ ν•„μš”λ‘œ ν•˜μ§€ μ•ŠλŠ” κ΅¬ν˜„ λ¬Έμ œμ΄λ‹€.
  2. κ΅¬ν˜„ν•΄μ•Όν•  μš”μ†ŒλŠ” 크게 λͺ¨λž˜λ°”λžŒμ˜ ν™•μ‚°κ³Ό ν† λ„€μ΄λ„μ˜ 이동이닀.
  3. λͺ¨λž˜λ°”λžŒμ˜ ν™•μ‚°
    1. λͺ¨λž˜λ°”λžŒμ΄ ν™•μ‚°λ˜λŠ” μ’Œν‘œλž‘ λΉ„μœ¨μ„ λ”•μ…”λ„ˆλ¦¬ ν˜•νƒœλ‘œ λ‹΄μ•„μ€€λ‹€. 더 λ˜‘λ˜‘ν•œ 방법도 μžˆμ„ κ±° 같은데 λ‚˜λŠ” κ·Έλƒ₯ λͺ¨λ“  μ’Œν‘œλž‘ λΉ„μœ¨μ„ 일일이 μž…λ ₯ν–ˆλ‹€ 이럴 경우 μ˜€νƒ€κ°€ 있으면 디버깅 μ‹œ λ°œκ²¬ν•˜κΈ° 맀우 νž˜λ“œλ‹ˆ μ£Όμ˜ν•˜μž
    2. λ”•μ…”λ„ˆλ¦¬μ— μ €μž₯ν•΄λ‘” μ’Œν‘œλž‘ λΉ„μœ¨λŒ€λ‘œ λͺ¨λž˜λ°”λžŒμ„ 이동 μ‹œν‚€λ©΄μ„œ λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜λŠ” λͺ¨λž˜κ°€ μžˆμ„ λ•Œλ§ˆλ‹€ μ†Œμ‹€λœ λͺ¨λž˜μ˜ 양에 더해쀀닀. 
  4. ν† λ„€μ΄λ„μ˜ 이동
    1. 토넀이도가 μ΄λ™ν•˜λŠ” κ·œμΉ™μ„ νŒŒμ•…ν•΄μ•Όν•˜λŠ”λ° 이게 생각보닀 쑰금 λ³΅μž‘ν•˜λ‹€
    2. μ€‘μ•™μ—μ„œ μ‹œμž‘ν•΄μ„œ ν˜„μž¬ λ°©ν–₯으둜 k번 μ΄λ™ν•˜λ©΄ λ°©ν–₯이 λ°”λ€Œκ³  λ°©ν–₯이 두 번 λ°”λ€Œλ©΄ kκ°€ 1μ”© μ¦κ°€ν•˜λŠ” κ·œμΉ™μ΄λ‹€. κΈ€λ‘œ μ„€λͺ…ν•˜λ‹ˆ μ’€ λ³΅μž‘ν•œλ° 직접 그림으둜 그렀보면 이해가 쉽닀. ν—·κ°ˆλ¦¬λ©΄ μ—°μŠ΅μœΌλ‘œ 빈 λ¦¬μŠ€νŠΈμ— 1λΆ€ν„° μ±„μ›Œλ‚˜κ°€λŠ” μ½”λ“œλ₯Ό μ§œλ΄λ„ 도움이 λœλ‹€.
    3. μœ„ κ·œμΉ™λŒ€λ‘œ μ΄λ™ν•˜λ©΄μ„œ λͺ¨λž˜λ°”λžŒμ΄ 있으면 λͺ¨λž˜λ°”λžŒμ„ κ·œμΉ™λŒ€λ‘œ ν™•μ‹  μ‹œμΌœμ€€λ‹€.
  5. ν† λ„€μ΄λ„μ˜ 이동을 κ΅¬ν˜„ν•˜λŠ” 게 생각보닀 λ³΅μž‘ν–ˆλ˜ λ¬Έμ œμ΄λ‹€.
  6. μ²˜μŒμ— λ°©ν–₯ 정보 μž…λ ₯ν•  λ•Œ μ˜€νƒ€λ‚˜μ§€ μ•Šλ„λ‘ κΌ­ μ£Όμ˜ν•΄μ•Όν•˜κ³  λ‹€λ₯Έ κ³ μˆ˜λΆ„λ“€ 풀이 λ³΄λ‹ˆκΉŒ μ•„μ˜ˆ U, D, L, R 같이 λ°©ν–₯을 문자 ν˜•νƒœλ‘œ μ €μž₯ν•΄μ„œ μ΄μš©ν•˜λ˜λ° μ΄λ ‡κ²Œ λ¬Έμ œμ— μž…λ ₯ν•΄μ•Όν•  μ’Œν‘œκ°€ λ§Žμ•„ ν—·κ°ˆλ¦¬κΈ° μ‰¬μš΄ κ²½μš°μ—λŠ” ν•΄λ‹Ή 방법도 쒋은 것 κ°™λ‹€. 

<μ •λ‹΅ μ½”λ“œ>

import sys, os, io, atexit

input = lambda: sys.stdin.readline().rstrip('\r\n')
stdout = io.BytesIO()
sys.stdout.write = lambda s: stdout.write(s.encode("ascii"))
atexit.register(lambda: os.write(1, stdout.getvalue()))

# 220921 20057 λ§ˆλ²•μ‚¬ 상어와 토넀이도

# μ •λ‹΅μ½”λ“œ

# directions: λͺ¨λž˜λ°”λžŒ ν™•μ‚° μ’Œν‘œμ™€ ν•΄λ‹Ή μ’Œν‘œμ˜ λͺ¨λž˜ λΉ„μœ¨
directions = {
    0 : [(-2, 0, 2), (-1, -1, 10), (-1, 0, 7), (-1, 1, 1), (0, -2, 5), (1, -1, 10), (1, 0, 7), (1, 1, 1), (2, 0, 2), (0, -1)],
    1 : [(-1, -1, 1), (-1, 1, 1), (0, -2, 2), (0, -1, 7), (0, 1, 7), (0, 2, 2), (1, -1, 10), (1, 1, 10), (2, 0, 5), (1, 0)],
    2 : [(-2, 0, 2), (-1, -1, 1), (-1, 0, 7), (-1, 1, 10), (0, 2, 5), (1, -1, 1), (1, 0, 7), (1, 1, 10), (2, 0, 2), (0, 1)],
    3 : [(-2, 0, 5), (-1, -1, 10), (-1, 1, 10), (0, -2, 2), (0, -1, 7), (0, 1, 7), (0, 2, 2), (1, -1, 1), (1, 1, 1), (-1, 0)]
}

# torando: 토넀이도 ν•¨μˆ˜
def tornado (r, c, sand, d):
    # κΈ€λ‘œλ²Œ λ³€μˆ˜ μ„ μ–Έ
    global lost

    # left: λ‚¨μ•„μžˆλŠ” λͺ¨λž˜μ˜ μ–‘
    left = sand
    
    # 토넀이도λ₯Ό μ‹œμ „ν•œ 칸의 λͺ¨λž˜λŠ” 0이 λœλ‹€.
    arr[r][c] = 0
    
    # λͺ¨λž˜κ°€ λΉ„μœ¨λŒ€λ‘œ ν•΄λ‹Ή μ’Œν‘œλ‘œ ν™•μ‚°ν•œλ‹€
    for direction in directions[d][:-1]:
        nr = r + direction[0]
        nc = c + direction[1]
        # μ›λž˜ λͺ¨λž˜μ˜ μ–‘ κ°μ†Œ
        left -= (sand * direction [2]) // 100
        
        # λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜μ§€ μ•ŠμœΌλ©΄ ν•΄λ‹Ή μ’Œν‘œμ— λͺ¨λž˜λ₯Ό ν‘œμ‹œν•΄μ€€λ‹€.
        if 0 <= nr < N and 0 <= nc < N:
            arr[nr][nc] += (sand *direction[2]) // 100
        # λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜λŠ” λͺ¨λž˜λŠ” μ†Œμ‹€λœλ‹€.
        else:
            lost += (sand * direction[2]) // 100
    

    # nr, nc: ν™•μ‚°λ˜κ³  남은 λͺ¨λž˜κ°€ μœ„μΉ˜ν•  μ’Œν‘œ 
    nr = r + directions[d][-1][0]
    nc = c + directions[d][-1][1]

    # λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜μ§€ μ•ŠμœΌλ©΄ ν•΄λ‹Ή μ’Œν‘œμ— λͺ¨λž˜ ν‘œμ‹œ
    if 0 <= nr < N and 0 <= nc < N:
        arr[nr][nc] += left
    # λ²”μœ„ λ²—μ–΄λ‚˜λ©΄ μ†Œμ‹€
    else:
        lost += left

    return 

# N: λ°°μ—΄μ˜ 크기, arr: λͺ¨λž˜ λ°°μ—΄
N = int(input())
arr = [list(map(int, input().split())) for _ in range(N)]

# lost: 격자 λ°–μœΌλ‘œ λ‚˜κ°€ μ†Œμ‹€λœ λͺ¨λž˜μ˜ μ–‘
lost = 0

# 델타 탐색 λ°©ν–₯ μ„€μ •
dr = [0, 1, 0, -1]
dc = [-1, 0, 1, 0]

# r, c: μ‹œμž‘ μœ„μΉ˜, d: 토넀이도 이동 λ°©ν–₯
r = N // 2
c = N // 2
d = 0

# change: ν•΄λ‹Ή λ°©ν–₯으둜 λͺ‡ 번 이동해야 λ°©ν–₯이 λ°”λ€ŒλŠ”μ§€λ₯Ό λ‚˜νƒ€λ‚΄λŠ” λ³€μˆ˜
change = 1
# cnt: ν•΄λ‹Ή λ°©ν–₯으둜 μ΄λ™ν•œ 횟수
cnt = 0
# flag_cnt: change λ³€μˆ˜μ˜ 증가λ₯Ό λ‚˜νƒ€λ‚΄λŠ” λ³€μˆ˜
flag_cnt = 0

# μ€‘μ•™μ—μ„œλΆ€ν„° 토넀이도 이동
for i in range(N*N - 1):
    # ν•΄λ‹Ή λ°©ν–₯으둜 μ΄λ™ν•œ 횟수λ₯Ό μ„Έμ€€λ‹€.
    cnt += 1

    # 토넀이도 이동
    r += dr[d]
    c += dc[d]

    # μ΄λ™ν•œ μœ„μΉ˜μ— λͺ¨λž˜λ°”λžŒμ΄ 있으면 토넀이도 μ‹œν–‰
    if arr[r][c]:
        tornado(r, c, arr[r][c], d)

    # change만큼 이동 ν–ˆμœΌλ©΄ λ°©ν–₯을 λ°”κΏ”μ€€λ‹€.
    if cnt == change:
        d = (d + 1) % 4
        # cnt: μ΄ˆκΈ°ν™”
        cnt = 0
        # flag_cntλ₯Ό μ„Έμ€€λ‹€.
        flag_cnt += 1

        # flag_cntκ°€ 2κ°€ 되면 changeλ₯Ό 1 늘렀주고 flag_cntλ₯Ό μ΄ˆκΈ°ν™” ν•΄μ€€λ‹€.
        if flag_cnt == 2:
            change += 1
            flag_cnt = 0


print(lost)

λŒ“κΈ€