[문제풀이-백준] 20057. 마법사 상어와 토네이도
풀이
시뮬레이션
처음 생각했던 방법
- 모래를 계산할 때, 좌표, 방향에 따라 모두 if 분기를 하려고 하니 200라인이 넘어감
개선 방법
-
델타를 이용하되 dy,dx로 쪼갤 것
-
총 방향은 4개이고, 모래가 날아가는 횟수는 10이므로 델타는 [4][10]이면 된다.
풀이 방법
-
토네이도 이동 함수
- 무조건 꺾어지려는 성질 이용
-
이동 방향에 따라 날아가는 모래 양 계산 함수
-
모래가 밖으로 날아갈 때마다 answer에 추가
코드
import math
def move(y,x,d,ans):
total = 0
for dir in range(9):
ny, nx = y + dy[d][dir], x + dx[d][dir]
# 1%
if dir == 0 or dir == 1:
sand = math.floor(links[y][x] * 0.01)
# 2%
elif dir == 2 or dir == 3:
sand = math.floor(links[y][x] * 0.02)
# 7%
elif dir == 4 or dir == 5:
sand = math.floor(links[y][x] * 0.07)
# 10%
elif dir == 6 or dir == 7:
sand = math.floor(links[y][x] * 0.1)
# 5%
else:
sand = math.floor(links[y][x] * 0.05)
if 0 <= ny < N and 0 <= nx < N:
links[ny][nx] += sand
else:
ans += sand
total += sand
# 나머지
ny, nx = y + dy[d][9], x + dx[d][9]
links[y][x] -= total
if 0 <= ny < N and 0 <= nx < N:
links[ny][nx] += links[y][x]
else:
ans += links[y][x]
links[y][x] = 0
return ans
def tornado(by,bx,bd):
nd = (bd+1) % 4
ny,nx = by+direct[nd][0],bx+direct[nd][1]
# if 0 <= ny < N and 0 <= nx < N:
if visited[ny][nx]:
ny,nx,nd = by+direct[bd][0],bx+direct[bd][1],bd
visited[ny][nx] = True
return ny,nx,nd
else:
visited[ny][nx] = True
return ny,nx,nd
N = int(input())
links = [list(map(int,input().split())) for _ in range(N)]
y = x = N // 2
d = 3
answer = 0
direct = [(0,-1),(1,0),(0,1),(-1,0)]
visited = [[False]*N for _ in range(N)]
visited[y][x] = True
dy = [
[-1,1,-2,2,-1,1,-1,1,0,0], # 10 # 1%,2%,7%,10%,5%,나머지
[-1,-1,0,0,0,0,1,1,2,1],
[-1,1,-2,2,-1,1,-1,1,0,0],
[1,1,0,0,0,0,-1,-1,-2,-1],
]
dx = [
[1,1,0,0,0,0,-1,-1,-2,-1],
[-1,1,-2,2,-1,1,-1,1,0,0],
[-1,-1,0,0,0,0,1,1,2,1],
[-1,1,-2,2,-1,1,-1,1,0,0],
]
while True:
y,x,d = tornado(y,x,d)
answer = move(y,x,d,answer)
if (y,x) == (0,0):
break
print(answer)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main20057_마법사상어와토네이도 {
private static int N;
private static int[][] links;
private static boolean[][] visited;
private static int[][] direct = {
{0,-1},
{1,0},
{0,1},
{-1,0},
};
private static int[][] dy = {
{-1,1,-2,2,-1,1,-1,1,0,0}, // 10 # 1%,2%,7%,10%,5%,나머지
{-1,-1,0,0,0,0,1,1,2,1},
{-1,1,-2,2,-1,1,-1,1,0,0},
{1,1,0,0,0,0,-1,-1,-2,-1},
};
private static int[][] dx = {
{1,1,0,0,0,0,-1,-1,-2,-1},
{-1,1,-2,2,-1,1,-1,1,0,0},
{-1,-1,0,0,0,0,1,1,2,1},
{-1,1,-2,2,-1,1,-1,1,0,0},
};
public static int move(int y, int x, int d, int ans) {
int total = 0;
int sand = 0;
int ny, nx;
for (int dir=0; dir<9; dir++) {
ny = y + dy[d][dir];
nx = x + dx[d][dir];
if (dir == 0 || dir == 1) {
// 1%
sand = (int) Math.floor(links[y][x] * 0.01);
} else if (dir == 2 || dir ==3) {
// 2%
sand = (int) Math.floor(links[y][x] * 0.02);
} else if (dir ==4 || dir == 5) {
// 7%
sand = (int) Math.floor(links[y][x] * 0.07);
} else if (dir == 6 || dir == 7) {
// 10%
sand = (int) Math.floor(links[y][x] * 0.1);
} else {
// 5%
sand = (int) Math.floor(links[y][x] * 0.05);
}
if (0 <= ny && ny < N && 0 <= nx && nx < N) {
links[ny][nx] += sand;
} else {
ans += sand;
}
total += sand;
}
// 나머지
ny = y + dy[d][9];
nx = x + dx[d][9];
links[y][x] -= total;
if (0 <= ny && ny < N && 0 <= nx && nx < N) {
links[ny][nx] += links[y][x];
} else {
ans += links[y][x];
}
links[y][x] = 0;
return ans;
}
public static int[] tornado(int by, int bx, int bd) {
int nd = (bd+1) % 4;
int ny = by+direct[nd][0];
int nx = bx+direct[nd][1];
int[] result = new int[4];
if (visited[ny][nx]) {
ny = by+direct[bd][0];
nx = bx+direct[bd][1];
nd = bd;
}
visited[ny][nx] = true;
result[0] = ny;
result[1] = nx;
result[2] = nd;
return result;
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine()," ");
N = Integer.parseInt(st.nextToken());
links = new int[N][N];
for (int i=0; i<N; i++) {
st = new StringTokenizer(br.readLine()," ");
for (int j=0; j<N; j++) {
links[i][j] = Integer.parseInt(st.nextToken());
}
}
int y = N / 2;
int x = N / 2;
int d = 3;
int answer = 0;
visited = new boolean[N][N];
visited[y][x] = true;
int[] result = new int[] {y,x,d};
while (true) {
result = tornado(result[0],result[1],result[2]);
answer = move(result[0],result[1],result[2],answer);
if (result[0] == 0 && result[1] == 0) {
break;
}
}
System.out.println(answer);
}
}
Author And Source
이 문제에 관하여([문제풀이-백준] 20057. 마법사 상어와 토네이도), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@psj8532/문제풀이-백준-20057.-마법사-상어와-토네이도저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)