백준 20057 - 마법사 상어와 토네이도
Updated:
Java
20057 번 - 마법사 상어와 토네이도
문제
접근 방법
전체적인 구현 순서는 다음과 같다.
- 회전하는 토네이도 이동방향 구현
- 방향에 따른 퍼지는 모래의 비율 2차원 List로 설정
- 모래를 퍼뜨린다
토네이도의 회전 방향은 [좌 -> 하] / [우 -> 상] 이 각각 반복 될 때 마다, 2칸 씩 더 이동하도록 하였다.
MAP 크기는 의도적으로 행/렬 4줄씩 늘려서 Map 외부로 모래가 퍼지는 값을 저장하도록 하였다.
따라서, MAP 내부는 (2 <= y < n + 2) , (2 <= x < n + 2) 이다.
토네이도에 의하여 모래가 퍼지는 위치(비율)은,
우선 좌측으로 토네이도가 이동할 때 모래가 퍼지는 위치와 비율을 2차원 배열로 저장하였고,
위 행렬을 90도씩 회전시키면서 좌,우,상 방향의 퍼지는 위치와 비율을 계산하였다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int n, result;
static int[][] map;
// 좌, 하, 우, 상
static int[] dy = {0,1,0,-1};
static int[] dx = {-1,0,1,0};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk;
n = stoi(br.readLine());
map = new int[n + 4][n + 4];
for(int i = 2; i < n + 2; i++) {
stk = new StringTokenizer(br.readLine());
for(int j = 2; j < n + 2; j++) {
map[i][j] = stoi(stk.nextToken());
}
}
int dir = 0, dist = 1;
int moveCnt = 0;
int y = (n / 2) + 2;
int x = (n / 2) + 2;
makeWind();
// 토네이도 이동
end : while(true) {
for(int rp = 0; rp < 2; rp++) {
for(int i = 0; i < dist; i++) {
// 마지막 점 도달
if(moveCnt == (n * n) - 1)
break end;
y = y + dy[dir];
x = x + dx[dir];
// 현재 토네이도 위치에서 모래를 퍼뜨린다.
Spread(y,x,dir);
moveCnt++;
}
dir = (dir + 1) % 4;
}
dist++;
}
// 전체 모래의 개수를 더 한다.
for(int i = 0; i < n + 4; i++) {
for(int j = 0; j < n + 4; j++) {
result += map[i][j];
}
}
// map 범위 내부에 남아있는 모래의 개수를 뺀다.
for(int i = 2; i < n + 2; i++) {
for(int j = 2; j < n + 2; j++) {
result -= map[i][j];
}
}
System.out.println(result);
br.close();
}
// 모래를 퍼뜨린다.
static List<int[][]> wind;
static void Spread(int y, int x, int dir) {
int ny,nx, calS;
int sum = 0;
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 5; j++) {
// 해당 방향으로 토네이도가 모래를 밀쳤을 때 밀린다면,
if(wind.get(dir)[i][j] != 0) {
ny = y + (i - 2);
nx = x + (j - 2);
calS = (map[y][x] * wind.get(dir)[i][j]) / 100;
map[ny][nx] += calS;
sum += calS;
}
}
}
ny = y + dy[dir];
nx = x + dx[dir];
map[ny][nx] += (map[y][x] - sum);
map[y][x] = 0;
}
// 모래 퍼뜨리는 위치
static void makeWind() {
wind = new ArrayList<>();
// 좌
int[][] temp = new int[5][5];
temp[0][2] = 2;
temp[1][1] = 10;
temp[1][2] = 7;
temp[1][3] = 1;
temp[2][0] = 5;
temp[3][1] = 10;
temp[3][2] = 7;
temp[3][3] = 1;
temp[4][2] = 2;
wind.add(temp);
// 하
int[][] rotate = new int[5][5];
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 5; j++) {
rotate[i][j] = temp[j][5-1-i];
}
}
wind.add(rotate);
// 우
rotate = new int[5][5];
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 5; j++) {
rotate[i][j] = temp[5 - 1 - i][5 - 1 - j];
}
}
wind.add(rotate);
// 상
rotate = new int[5][5];
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 5; j++) {
rotate[i][j] = temp[5 - 1 - j][i];
}
}
wind.add(rotate);
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}