https://www.acmicpc.net/problem/21610
21610번: 마법사 상어와 비바라기
마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기
www.acmicpc.net
public class 마법사상어와비바라기 {
static int N, M;
static int map[][];
static boolean cloud[][];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N + 1][N + 1];
cloud = new boolean[N + 1][N + 1]; // 구름의 상태 정보
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 1; j <= N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
initCloud();
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
// 1.
moveCloud(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
// 2.
drawRain();
// 3. 물복사
copyWater();
// 4. 구름 갱신
refreshCloud();
}
System.out.println(sumWater());
}
private static int sumWater() {
int sum = 0;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
sum += map[i][j];
}
}
return sum;
}
private static void refreshCloud() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (cloud[i][j] == true) {
cloud[i][j] = false;
} else if (map[i][j] >= 2) {
cloud[i][j] = true;
map[i][j] -=2;
}
}
}
}
private static void copyWater() {
int dx[] = { -1, -1, 1, 1 }; // 대각선 영역만 검사
int dy[] = { -1, 1, 1, -1 };
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (cloud[i][j] == true) {
int sum = 0;
for (int d = 0; d < 4; d++) {
int nx = i + dx[d];
int ny = j + dy[d];
if (nx < 1 || nx > N || ny < 0 || ny > N)
continue;
if (map[nx][ny] > 0) // 물이 없었는데 더해져서 생기는 경우를 체크할 필요가 없다
sum++;
}
map[i][j] += sum;
}
}
}
}
private static void drawRain() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (cloud[i][j] == true) {
map[i][j]++;
}
}
}
}
private static void moveCloud(int d, int s) {
// 왼쪽부터 시계방향
int dx[] = { 0,0, -1, -1, -1, 0, 1, 1, 1 };
int dy[] = { 0, -1, -1, 0, 1, 1, 1, 0, -1 };
boolean tempCloud[][] = new boolean[N+1][N+1];
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (cloud[i][j] == true) {
int nx = (i+dx[d]*s)%N;
int ny = (j+dy[d]*s)%N;
if(nx == 0) nx = N;
else if(nx < 0 ) nx= N+nx;
if(ny == 0) ny = N;
else if(ny < 0) ny = N+ny;
tempCloud[nx][ny] = true;
}
}
}
cloud = tempCloud;
}
private static void initCloud() {
cloud[N][1] = true;
cloud[N][2] = true;
cloud[N - 1][1] = true;
cloud[N - 1][2] = true;
}
}
간단한 시뮬레이션 문제였습니다.
우선 맵의 정보를 나타낼 2차원 배열 map[][]과 구름의 위치를 나타낼 cloud[][] 를 선언했습니다.
입력값을 다 받은 후
첫번째로 구름 이동을 하는 moveCloud 메서드입니다.
조건으로는 cloud 배열을 통해 검사하고
이동한 값을 tempCloud 배열에 저장한 다음 cloud를 tempCloud로 갱신해주었습니다.
여기서 구름 이동은 N=8이라고 하였을 때 1 ~ 8 을 기준으로
-15 ~ -8
-7 ~ 0
1 ~ 8
9 ~ 16
17 ~ 24
0보다 클때는 nx = ( 현재위치 + 이동거리 ) % N 이고
0보다 작을때는 nx = N + ( 현재위치 +이동거리 ) % N 입니다.
그 다음 둘다 nx가 0일 때는 N으로 갱신해주어야 합니다.
나머지 로직들은 간단하게 구현할 수 있었습니다.
'알고리즘' 카테고리의 다른 글
[백준] 14719 빗물 - java (0) | 2021.06.29 |
---|---|
[백준] 20057 마법사 상어와 토네이도 - java (0) | 2021.06.27 |
[프로그래머스] 문자열 내 마음대로 정렬하기 - java (0) | 2021.06.24 |
[백준] 1068 트리 - java (0) | 2021.06.18 |
[프로그래머스] [3차]압축 - java (0) | 2021.05.07 |