https://www.acmicpc.net/problem/20057
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N, answer;
static int[] tornado;
static int[] direction = {2, 1, 0, 3}; // 0: 우, 1: 하, 2: 좌, 3: 상
static int[][] movedAmount = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
static int[][][] neighbor = {{{-1, 1}, {1, 1}, {-1, 0}, {1, 0}, {-2, 0}, {2, 0}, {-1, -1}, {1, -1}, {0, 2}},
{{1, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -2}, {0, 2}, {-1, -1}, {-1, 1}, {2, 0}},
{{-1, -1}, {1, -1}, {-1, 0}, {1, 0}, {-2, 0}, {2, 0}, {-1, 1}, {1, 1}, {0, -2}},
{{-1, -1}, {-1, 1}, {0, -1}, {0, 1}, {0, -2}, {0, 2}, {1, -1}, {1, 1}, {-2, 0}}};
static double[] percent = {0.1, 0.1, 0.07, 0.07, 0.02, 0.02, 0.01, 0.01, 0.05};
static int[][] map;
static void input() {
Reader scanner = new Reader();
N = scanner.nextInt();
map = new int[N][N];
for(int row = 0; row < N; row++) {
for(int col = 0; col < N; col++) map[row][col] = scanner.nextInt();
}
}
static void solution() {
answer = 0;
tornado = new int[] {N / 2, N / 2};
int count = 0;
for(int moveNum = 1; moveNum < N; moveNum++) {
for(int repeat = 0; repeat < (moveNum == N - 1 ? 3 : 2); repeat++) {
for(int cont = 0; cont < moveNum; cont++) {
int dir = direction[count % 4];
int[] movedLoc = new int[] {tornado[0] + movedAmount[dir][0], tornado[1] + movedAmount[dir][1]};
move(movedLoc, dir);
tornado = movedLoc;
}
count++;
}
}
System.out.println(answer);
}
static void move(int[] loc, int dir) {
int sand = map[loc[0]][loc[1]], original = map[loc[0]][loc[1]];
for(int idx = 0; idx < percent.length; idx++) {
int[] spreadLoc = new int[] {loc[0] + neighbor[dir][idx][0], loc[1] + neighbor[dir][idx][1]};
int spreadAmount = (int)Math.floor(original * percent[idx]);
sand -= spreadAmount;
if(!isInMap(spreadLoc[0], spreadLoc[1])) {
answer += spreadAmount;
continue;
}
map[spreadLoc[0]][spreadLoc[1]] += spreadAmount;
}
if(isInMap(loc[0] + movedAmount[dir][0], loc[1] + movedAmount[dir][1])) {
map[loc[0] + movedAmount[dir][0]][loc[1] + movedAmount[dir][1]] += sand;
} else {
answer += sand;
}
map[loc[0]][loc[1]] = 0;
}
static boolean isInMap(int x, int y) {
if(x < 0 || x >= N || y < 0 || y >= N) return false;
return true;
}
public static void main(String[] args) {
input();
solution();
}
static class Reader {
BufferedReader br;
StringTokenizer st;
public Reader() {
br = new BufferedReader(new InputStreamReader(System.in));
}
String next() {
while(st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
}
}
토네이도의 규칙
1. 토네이도는 왼쪽, 아래쪽, 오른쪽, 위쪽 방향 순서로 반복하며 움직입니다.
2. 토네이도는 (왼쪽, 아래쪽), (오른쪽, 위쪽) 쌍을 이뤄 움직인다고 볼 수 있는데, 한 번 쌍이 움직일 때 움직이는 칸 수가 한 칸씩 늘어납니다.예를 들어, 처음 움직일 때 (왼쪽, 아래쪽)을 움직이는데, 이 때는 각각 한 칸을 움직이고 그 다음 움직일 때는 (오른쪽, 위쪽)을 움직이는데 이 때는 각각 두 칸을 움직입니다. 그 다음 세 번째 움직일 때는 다시 (왼쪽, 아래쪽)을 움직이는 이 때는 각각 세 칸을 움직입니다.
- 그러나 마지막 움직임 때는 두 개가 쌍을 이루는 것이 아닌 세 개가 쌍을 이뤄 움직입니다.
- 한 쌍의 움직임을 한 번이라고 봤을 때, 총 움직임은 N - 1번 일어납니다.
즉, 격자가 5 x 5 크기라면, 총 4번 움직이는데, 움직이는 순서는 (왼쪽, 아래쪽), (오른쪽, 위쪽), (왼쪽, 아래쪽), (오른쪽, 위쪽, 왼쪽) 순서로 움직입니다.