토네이도의 방향 순서가 서쪽 -> 남쪽 -> 동쪽 -> 북쪽 순서대로 반복된다.
direct 3차원 배열을 만들어서,
- 첫 번째 인덱스는 방향(0: 서쪽, 1:남쪽, 2:동쪽, 3:북쪽)을 의미하고,
- 두 번째 인덱스는 0일 경우 r 좌표(행 좌표), 1일 경우 c 좌표(열 좌표)를 나타내었다.
- 세 번째 인덱스는 현재 위치를 기준으로 1%비율에 해당하는 위치, 2%에 해당하는 위치,
5%에 해당하는 위치, 7%에 해당하는 위치, 10%에 해당하는 위치, 알파에 해당하는 위치를 나타냈다.
int[][][] direct = new int[4][2][10];
{
{ { 1, -1, 2, -2, 0, 1, -1, 1, -1, 0 }, { 1, 1, 0, 0, -2, 0, 0, -1, -1, -1 } }, <- 서쪽 방향일 때 각 비율의 좌표
{ { -1, -1, 0, 0, 2, 0, 0, 1, 1, 1 }, { -1, 1, -2, 2, 0, -1, 1, -1, 1, 0 } }, <- 남쪽 방향일 때 각 비율의 좌표
{ { 1, -1, 2, -2, 0, 1, -1, 1, -1, 0 }, { -1, -1, 0, 0, 2, 0, 0, 1, 1, 1 } }, <- 동쪽 방향일 때 각 비율의 좌표
{ { 1, 1, 0, 0, -2, 0, 0, -1, -1, -1 }, { -1, 1, -2, 2, 0, -1, 1, -1, 1, 0 } } <- 북쪽 방향일 때 각 비율의 좌표
};
예를 들어, 위의 그림은 현재 토네이도가 서쪽방향으로 부는 경우에 해당한다.
만약 모래의 기존 위치가 (r, c)일 때 7%인 위치를 찾으려면?
: 먼저 현재 방향은 서쪽이므로 첫번째 인덱스는 0이 된다. (0: 서쪽, 1:남쪽, 2:동쪽, 3:북쪽) -> direct[0][?][?]
그리고 세번째 인덱스에서 7%에 해당하는 인덱스는 아래의 빨간색 부분이다. (인덱스 5와 6)
-> direct[0][?][5] & direct[0][?][6]
{
{ { 1, -1, 2, -2, 0, 1, -1, 1, -1, 0 }, { 1, 1, 0, 0, -2, 0, 0, -1, -1, -1 } }, <- 서쪽 방향일 때 각 비율의 좌표
{ { -1, -1, 0, 0, 2, 0, 0, 1, 1, 1 }, { -1, 1, -2, 2, 0, -1, 1, -1, 1, 0 } }, <- 남쪽 방향일 때 각 비율의 좌표
{ { 1, -1, 2, -2, 0, 1, -1, 1, -1, 0 }, { -1, -1, 0, 0, 2, 0, 0, 1, 1, 1 } }, <- 동쪽 방향일 때 각 비율의 좌표
{ { 1, 1, 0, 0, -2, 0, 0, -1, -1, -1 }, { -1, 1, -2, 2, 0, -1, 1, -1, 1, 0 } } <- 북쪽 방향일 때 각 비율의 좌표
};
두번째 인덱스는 0일 때 r 좌표, 1일 때 c 좌표이다.
따라서 7% 비율에 해당하는 위치는
(r + direct[0][0][5], c + direct[0][1][5]) 와 (r + direct[0][0][6], c + direct[0][1][6])이다.
moveSand() 메서드는 y에 있는 모래가 0보다 클 때, 그 모래를 비율에 맞춰 흩어보내는 메서드이다.
위의 direct 배열을 이용하여 모래를 적절히 분배하고, 만약 NxN 범위를 벗어나면 경계 밖으로 나간 것이므로 total에 나간 모래양만큼 더해준다.
public static void moveSand(int r, int c, int d) {
int rest = A[r][c]; // 기존의 모래양
for (int i = 0; i < 9; i++) { // 9가지 경우에 맞추어 모래 흩뿌리기
int nr = r + direct[d][0][i];
int nc = c + direct[d][1][i];
int amount = (int) Math.floor(A[r][c] * (double) (percent[i] / 100.0));
rest -= amount;
// 경계 안에 있으면 기존의 모래양에 amount 더해주기
if ((1 <= nr && nr <= N) && (1 <= nc && nc <= N)) {
A[nr][nc] += amount;
}
else // 경계를 벗어나면 total에 모래양 더하기
total += amount;
}
int nr = r + direct[d][0][9]; // (r,c)를 기준으로 알파의 r 좌표
int nc = c + direct[d][1][9]; // (r,c)를 기준으로 알파의 c 좌표
// 경계 안에 있으면 기존의 모래양에 amount 더해주기
if ((1 <= nr && nr <= N) && (1 <= nc && nc <= N)) {
A[nr][nc] += rest;
A[r][c] = 0;
}
else // 경계를 벗어나면 total에 모래양 더하기
total += rest;
}
전체 코드 :
'BOJ > 삼성 SW 역량테스트' 카테고리의 다른 글
[백준 20055번] 컨베이어 벨트 위의 로봇 (java) (0) | 2021.04.21 |
---|---|
[백준 19237번] 어른 상어 (java) (0) | 2021.04.20 |
[백준 20061번] 모노미노도미노 2 (java) (0) | 2021.04.17 |
[백준 17822번] 원판 돌리기 (java) (0) | 2021.04.15 |
[백준 17837번] 새로운 게임 2 (java) (0) | 2021.04.14 |