백준 20057 마법사 상어와 토네이도

gmlwlswldbs·2021년 10월 21일
1

코딩테스트

목록 보기
59/130
import copy
n = int(input())
a = [list(map(int, input().split())) for _ in range(n)]
dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]
dir = [0] * (n * n - 1)
# sand[방향][1 ~ 9] = 
sand = [[[-1, 0, 0.01], [1, 0, 0.01], [-1, -1, 0.07], [1,-1, 0.07], [-2, -1, 0.02], [2, -1, 0.02], [-1, -2, 0.1], [1, -2, 0.1], [0, -3, 0.05]],
[[0, -1, 0.01], [0, 1, 0.01], [1, -1, 0.07], [1, 1, 0.07], [1, -2, 0.02], [1, 2, 0.02], [2, -1, 0.1], [2, 1, 0.1], [3, 0, 0.05]],
[[1, 0, 0.01], [-1, 0, 0.01], [-1, 1, 0.07], [1, 1, 0.07], [-2, 1, 0.02], [2, 1, 0.02], [-1, 2, 0.1], [1, 2, 0.1], [0, 3, 0.05]],
[[0, -1, 0.01], [0, 1, 0.01], [-1, -1, 0.07], [-1, 1, 0.07], [-1, 2, 0.02], [-1, -2, 0.02], [-2, 1, 0.1], [-2, -1, 0.1], [-3, 0, 0.05]]]
i = 0
iter = 1
maxiter = 1
k = 0
# 방향 전환 배열 만들기
while True:
    if i == n * n - 1:
        break
    if iter < maxiter:
        dir[i] = k % 4   
        iter += 1
    elif iter == maxiter:
        dir[i] = k % 4 
        iter += 1 
        if dir[i] == 1 or dir[i] == 3:
            maxiter += 1
        k += 1
        iter = 1
    i += 1
    
def move_sand(fx, fy, tx, ty, ax, ay, d, a):
    ysand = a[tx][ty]
    out = 0
    for u in range(len(sand[d])):
        # 모래가 이동할 좌표
        sx, sy = fx + sand[d][u][0], fy + sand[d][u][1]
        # 격자밖으로 날라가는 모래들
        if sx < 0 or sy < 0 or sx >= n or sy >= n:
            out += int(ysand * sand[d][u][2])
        # y의 모래가 비율만큼 sx, sy로 이동
        else:
            a[sx][sy] += int(ysand * sand[d][u][2])
        # 어떻게 되든 y에 있는 모래 양은 줄어든다.
        a[tx][ty] -= int(ysand * sand[d][u][2])
    # 알파로 이동하는 양은 y에 남은 양과 같다
    # 알파가 밖으로 날아가면 날아가는 것에 추가
    if ax < 0 or ay < 0 or ax >= n or ay >= n:
        out += a[tx][ty]
    # 알파가 격자를 벗어나지 않는다면 
    else:
        a[ax][ay] += a[tx][ty]
    a[tx][ty] = 0
    return a, out

fx, fy = n // 2, n // 2
ans = 0
d = 0
while True:
    if fx == 0 and fy == 0:
        break
    # y의 좌표
    tx, ty = fx + dx[dir[d]], fy + dy[dir[d]]
    # 알파의 좌표
    ax, ay = tx + dx[dir[d]], ty + dy[dir[d]]
    a, out = move_sand(fx, fy, tx, ty, ax, ay, dir[d], a)
    ans += out
    d += 1
    fx, fy = tx, ty

print(ans)

하라는 대로 구현인데 정말 저 배열을 만들어야하나 고민이 좀 됐음
-> 다른 방법으로도 풀어보기(대칭이용)

n = int(input())
a = [list(map(int, input().split())) for _ in range(n)]
dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]
dir = [0] * (n * n - 1)
# sand[방향][1 ~ 9] = 
sand = [[[-1, 0, 0.01], [1, 0, 0.01], [-1, -1, 0.07], [1,-1, 0.07], [-2, -1, 0.02], [2, -1, 0.02], [-1, -2, 0.1], [1, -2, 0.1], [0, -3, 0.05]],
[[0, -1, 0.01], [0, 1, 0.01], [1, -1, 0.07], [1, 1, 0.07], [1, -2, 0.02], [1, 2, 0.02], [2, -1, 0.1], [2, 1, 0.1], [3, 0, 0.05]],
[[1, 0, 0.01], [-1, 0, 0.01], [-1, 1, 0.07], [1, 1, 0.07], [-2, 1, 0.02], [2, 1, 0.02], [-1, 2, 0.1], [1, 2, 0.1], [0, 3, 0.05]],
[[0, -1, 0.01], [0, 1, 0.01], [-1, -1, 0.07], [-1, 1, 0.07], [-1, 2, 0.02], [-1, -2, 0.02], [-2, 1, 0.1], [-2, -1, 0.1], [-3, 0, 0.05]]]
i = 0
iter = 1
maxiter = 1
k = 0
# 방향 전환 배열 만들기
while True:
    if i == n * n - 1:
        break
    if iter < maxiter:
        dir[i] = k % 4   
        iter += 1
    elif iter == maxiter:
        dir[i] = k % 4 
        iter += 1 
        if dir[i] == 1 or dir[i] == 3:
            maxiter += 1
        k += 1
        iter = 1
    i += 1
    
def move_sand(fx, fy, tx, ty, ax, ay, d):
    out = 0
    for u in range(len(sand[d])):
        # 모래가 이동할 좌표
        sx, sy = fx + sand[d][u][0], fy + sand[d][u][1]
        # 격자밖으로 날라가는 모래들
        if sx < 0 or sy < 0 or sx >= n or sy >= n:
            out += int(a[tx][ty] * sand[d][u][2])
        # y의 모래가 비율만큼 sx, sy로 이동
        else:
            a[sx][sy] += int(a[tx][ty] * sand[d][u][2])
        # 어떻게 되든 y에 있는 모래 양은 줄어든다.
        a[tx][ty] -= int(a[tx][ty] * sand[d][u][2])
    # 알파로 이동하는 양은 y에 남은 양과 같다
    # 알파가 밖으로 날아가면 날아가는 것에 추가
    if ax < 0 or ay < 0 or ax >= n or ay >= n:
        out += a[tx][ty]
        a[tx][ty] = 0
        return a, out
    # 알파가 격자를 벗어나지 않는다면 
    a[ax][ay] += a[tx][ty]
    a[tx][ty] = 0
    return a, out

fx, fy = n // 2, n // 2
ans = 0
d = 0
while True:
    if d == len(dir):
        break
    # y의 좌표
    tx, ty = fx + dx[dir[d]], fy + dy[dir[d]]
    # 알파의 좌표
    ax, ay = tx + dx[dir[d]], ty + dy[dir[d]]
    a, out = move_sand(fx, fy, tx, ty, ax, ay, dir[d])
    ans += out
    d += 1
    fx, fy = tx, ty

print(ans)

자꾸 배열 a가 변하는데 값을 갖다쓰니까 잘못된 값이 나왔음
-> deepcopy 썻는데 시간 초과 -> 어차피 하나의 값만 저장하니까 걍 변수로 저장

import copy
n = int(input())
a = [list(map(int, input().split())) for _ in range(n)]
dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]
dir = [0] * (n * n - 1)
# sand[방향][1 ~ 9] = 
sand = [[[-1, 0, 0.01], [1, 0, 0.01], [-1, -1, 0.07], [1,-1, 0.07], [-2, -1, 0.02], [2, -1, 0.02], [-1, -2, 0.1], [1, -2, 0.1], [0, -3, 0.05]],
[[0, -1, 0.01], [0, 1, 0.01], [1, -1, 0.07], [1, 1, 0.07], [1, -2, 0.02], [1, 2, 0.02], [2, -1, 0.1], [2, 1, 0.1], [3, 0, 0.05]],
[[1, 0, 0.01], [-1, 0, 0.01], [-1, 1, 0.07], [1, 1, 0.07], [-2, 1, 0.02], [2, 1, 0.02], [-1, 2, 0.1], [1, 2, 0.1], [0, 3, 0.05]],
[[0, -1, 0.01], [0, 1, 0.01], [-1, -1, 0.07], [-1, 1, 0.07], [-1, 2, 0.02], [-1, -2, 0.02], [-2, 1, 0.1], [-2, -1, 0.1], [-3, 0, 0.05]]]
i = 0
iter = 1
maxiter = 1
k = 0
# 방향 전환 배열 만들기
while True:
    if i == n * n - 1:
        break
    if iter < maxiter:
        dir[i] = k % 4   
        iter += 1
    elif iter == maxiter:
        dir[i] = k % 4 
        iter += 1 
        if dir[i] == 1 or dir[i] == 3:
            maxiter += 1
        k += 1
        iter = 1
    i += 1
    
def move_sand(fx, fy, tx, ty, ax, ay, d, a):
    tmp_a = copy.deepcopy(a)
    out = 0
    for u in range(len(sand[d])):
        # 모래가 이동할 좌표
        sx, sy = fx + sand[d][u][0], fy + sand[d][u][1]
        # 격자밖으로 날라가는 모래들
        if sx < 0 or sy < 0 or sx >= n or sy >= n:
            out += int(a[tx][ty] * sand[d][u][2])
        # y의 모래가 비율만큼 sx, sy로 이동
        else:
            tmp_a[sx][sy] += int(a[tx][ty] * sand[d][u][2])
        # 어떻게 되든 y에 있는 모래 양은 줄어든다.
        tmp_a[tx][ty] -= int(a[tx][ty] * sand[d][u][2])
    # 알파로 이동하는 양은 y에 남은 양과 같다
    # 알파가 밖으로 날아가면 날아가는 것에 추가
    if ax < 0 or ay < 0 or ax >= n or ay >= n:
        out += tmp_a[tx][ty]
    # 알파가 격자를 벗어나지 않는다면 
    else:
        tmp_a[ax][ay] += tmp_a[tx][ty]
    tmp_a[tx][ty] = 0
    return tmp_a, out

fx, fy = n // 2, n // 2
ans = 0
d = 0
while True:
    if fx == 0 and fy == 0:
        break
    # y의 좌표
    tx, ty = fx + dx[dir[d]], fy + dy[dir[d]]
    # 알파의 좌표
    ax, ay = tx + dx[dir[d]], ty + dy[dir[d]]
    a, out = move_sand(fx, fy, tx, ty, ax, ay, dir[d], a)
    ans += out
    d += 1
    fx, fy = tx, ty


print(ans)

deepcopy 로 시간 초과 난 코드 : 배열이 엄청나게 바뀌지 않는한 최대한 변수로 이용

0개의 댓글