본문 바로가기
백준

백준 20057번 : 마법사 상어와 토네이도

by Huiyeong 2021. 7. 21.

 문제

https://www.acmicpc.net/problem/20057

 

 

20057번: 마법사 상어와 토네이도

마법사 상어가 토네이도를 배웠고, 오늘은 토네이도를 크기가 N×N인 격자로 나누어진 모래밭에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 모래의 양을

www.acmicpc.net

20057 마법사 상어와 토네이도

 

 구현 방법 

  1. 방향 전환
    위 그림을 보면 depth가 1부터 2번씩 좌, 하, 우, 상 순으로 방향 전환 후 depth가 1씩 늘어가는 걸 확인할 수 있습니다.
  2. 모래가 흩날리는 과정
    상, 하, 좌, 우가 각자 다르지만 상하, 좌우로 묶어서 구분할 수 있습니다.

 

 구현 코드

package BOJ.Gold;

import java.io.*;
import java.util.*;

public class BOJ20057_마법사상어와토네이도 {
	static int N, depth, r, c, d, cnt, ans, dirTrans, depTrans;
	static int[][] map, dir = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
	
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());
		map = new int[N][N];
		StringTokenizer st = null;
		for (int r=0;r<N;r++) {
			st = new StringTokenizer(br.readLine());
			for (int c=0;c<N;c++) {
				map[r][c] = Integer.parseInt(st.nextToken());
			}
		}
		depth = 1;
		r = c = N/2;
		while(true) {
			if (r==0 && c==0) break;
			tornado();
			r += dir[d][0]; c += dir[d][1];
			if (++dirTrans==depth) { // 방향을 depth만큼 바꿨으면 
				dirTrans = 0;
				d = (d+1)%4; // 방향 전환
				if (++depTrans==2) { // 방향을 2번 전환했으면
					depTrans = 0;
					depth++; // depth 늘려주기
				}
			}
		}
		System.out.println(ans);
	}
	
	static void tornado() {
		int nr = r+dir[d][0];
		int nc = c+dir[d][1];
		cnt = 0;
		
		if (d%2==1) sand(nr, nc, 0, 2); // 좌, 우 일 때
		else sand(nr, nc, 1, 3); // 상, 하 일 때
		
		// a 위치에 남은 모래 양을 넣어준다.      
		if (isIn(nr+dir[d][0], nc+dir[d][1])) map[nr+dir[d][0]][nc+dir[d][1]] += map[nr][nc]-cnt;
		// a 위치가 격자를 벗어난 곳이면 ans에 더해준다. 
		else ans += map[nr][nc]-cnt;
	}
	
	static void sand(int nr, int nc, int d1, int d2) {
		// 1%
		sandMove(r + dir[d1][0], c + dir[d1][1], 1);
		sandMove(r + dir[d2][0], c + dir[d2][1], 1);
		// 2%
		sandMove(nr + dir[d1][0] * 2, nc + dir[d1][1] * 2, 2);
		sandMove(nr + dir[d2][0] * 2, nc + dir[d2][1] * 2, 2);
		// 5%
		sandMove(nr + dir[d][0] * 2, nc + dir[d][1] * 2, 5);
		// 7%
		sandMove(nr + dir[d1][0], nc + dir[d1][1], 7);
		sandMove(nr + dir[d2][0], nc + dir[d2][1], 7);
		// 10%
		sandMove(nr + dir[d][0] + dir[d1][0], nc + dir[d][1] + dir[d1][1], 10);
		sandMove(nr + dir[d][0] + dir[d2][0], nc + dir[d][1] + dir[d2][1], 10);
	}
	
	static void sandMove(int mr, int mc, int ratio) {
		int value = (int)(map[r+dir[d][0]][c+dir[d][1]]*ratio*0.01);
		// 격자 안이라면 지정 위치에 값을 더해줌
		if (isIn(mr, mc)) map[mr][mc]+=value;
		// 격자를 벗어난다면 ans에 대해줌
		else ans+=value; 
		
		// 모래가 전부 흩날린 후 남은 모래의 양을 a에 더해야 하기 때문에 cnt를 사용
		cnt+=value;
	}
	
	static boolean isIn(int nr, int nc) {
		return nr>=0 && nr<N && nc>=0 && nc<N;
	}
}

 

정답!

'백준' 카테고리의 다른 글

백준 2887번 : 행성 터널 (Java)  (0) 2022.02.07
백준 1113번 : 수영장 만들기  (0) 2021.07.23
백준 5212번 : 지구 온난화  (0) 2021.07.20
백준 14719번 : 빗물  (0) 2021.07.20
백준 5558번 : 치즈  (0) 2021.07.18