문제
https://www.acmicpc.net/problem/20057
20057번: 마법사 상어와 토네이도
마법사 상어가 토네이도를 배웠고, 오늘은 토네이도를 크기가 N×N인 격자로 나누어진 모래밭에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 모래의 양을
www.acmicpc.net
풀이
꽤나 무식하게 풀이했다.
- 토네이도가 회전하는 방식 구현
- 단순하게 사진보고 유추했다. 1의 길이가 2번 반복, 2의 길이가 반복.. 그러다 n-1의 길이는 3번 반복되더라.
반복되면서 방향은 계속 바뀌고.. 보이는 대로 구현했다. 밑의 사진을 보면 이해가 좀 더 쉽다.
- 단순하게 사진보고 유추했다. 1의 길이가 2번 반복, 2의 길이가 반복.. 그러다 n-1의 길이는 3번 반복되더라.
- 회전된 비율 배열
- 4방향이니까, 그냥 회전해서 좌표를 다 구하는 방식으로 했다. 사실 좀 무식하고 좌표하나 잘못적으면 틀리지만, 고작 4방향 8 개정도는 하드코딩해도 괜찮지 않을까해서 별 생각않고 노가다했다. (x좌표, y좌표, 비율) 형태로 저장했다.
- 값 갱신
- 비율이 있는 위치가 배열범위에 들어온다면, 값을 더해주고, 해당 값만큼 빼주면 된다.
대신 비율을 구하기위해서는 원본값을 가지고 있어야하기에 복사값하나를 만들어서 처리해주면 된다. - 범위밖이면은 답에 더해주면 된다. 그 외에 프로세스는 같다.
- 비율이 있는 위치가 배열범위에 들어온다면, 값을 더해주고, 해당 값만큼 빼주면 된다.
코드
from sys import stdin
def changeDir(d):
if d == 3: return 0
return d+1
def spreadSand(nx, ny, total, arr):
global answer, sand
leftSand = total
for val in arr:
tx = nx + val[0]
ty = ny + val[1]
percent = val[2]
# 범위 안에 들어가면
if 0 <= tx < n and 0 <= ty < n:
# alpha 파트가 아니라면
if percent != -1:
sand[tx][ty] += (total * percent // 100)
leftSand -= (total * percent // 100)
# alpha 파트일경우
else:
sand[tx][ty] += leftSand
# 범위 벗어나면 답에 더해주고, 총 값은 빼준다.
else:
if percent != -1:
answer += (total * percent // 100)
leftSand -= (total * percent // 100)
else:
answer += leftSand
def cycle(cnt, limit, x, y, d):
global dx, dy, sand, toTheUp, toTheDown, toTheLeft, toTheRight, answer
while True:
if cnt == limit:
return x, y
nx = x + dx[d]
ny = y + dy[d]
total = sand[nx][ny]
if d == 0: spreadSand(nx, ny, total, toTheLeft)
elif d == 1: spreadSand(nx, ny, total, toTheDown)
elif d == 2: spreadSand(nx, ny, total, toTheRight)
elif d == 3: spreadSand(nx, ny, total, toTheUp)
sand[nx][ny] = 0
x = nx
y = ny
cnt += 1
toTheLeft = [(1, 1, 1), (-1, 1, 1), (-1, 0, 7), (1, 0, 7), (2, 0, 2), (-2, 0, 2), (-1, -1, 10), (1, -1, 10), (0, -2, 5), (0, -1, -1)]
toTheDown = [(-1, 1, 1), (-1, -1, 1), (0, 1, 7), (0, -1, 7), (0, 2, 2), (0, -2, 2), (1, 1, 10), (1, -1, 10), (2, 0, 5), (1, 0, -1)]
toTheRight = [(-1, -1, 1), (1, -1, 1), (1, 0, 7), (-1, 0, 7), (2, 0, 2), (-2, 0, 2), (1, 1, 10), (-1, 1, 10), (0, 2, 5), (0, 1, -1)]
toTheUp = [(1, 1, 1), (1, -1, 1), (0, 1, 7), (0, -1, 7), (0, 2, 2), (0, -2, 2), (-1, 1, 10), (-1, -1, 10), (-2, 0, 5), (-1, 0, -1)]
# # 좌 하 우 상
dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]
answer = 0
# # x, y는 시작점
n = int(input())
x = y = (n//2)
d = 0
sand = [ list(map(int, stdin.readline().rstrip().split())) for _ in range(n) ]
limit = 1
while True:
if limit == n-1:
for _ in range(3):
x, y = cycle(0, limit, x, y, d)
d = changeDir(d)
limit += 1
elif limit < n-1:
for _ in range(2):
x, y = cycle(0, limit, x, y, d)
d = changeDir(d)
limit +=1
else:
break
print(answer)
후기
너무 코드를 구리게 짠 거 같다. 맞추면야 장땡이지만, ㅋㅋㅋ 규칙성 찾을 생각자체를 안하고 하드코딩식으로 풀이한 거 같다.
다른 코드들을 좀 확인해보니 방향에 따라 횟수를 설정했고, 비율배열도 하나만 저렇게 선언하고 나머지는 규칙에 따라 손쉽게 작성했더라.
'백준' 카테고리의 다른 글
21609 - 상어 중학교 (0) | 2023.07.07 |
---|---|
20058 - 마법사 상어와 파이어스톰 (0) | 2023.07.07 |
20056 - 마법사 상어와 파이어볼 (0) | 2023.07.05 |
19236 - 청소년 상어 (0) | 2023.07.04 |
19237 - 어른 상어 (0) | 2023.07.04 |