본문 바로가기
알고리즘/삼성 SW 역량 테스트 기출

백준 20057 마법사 상어와 토네이도 - 삼성 SW 역량 테스트 기출

by 호롤롤로루야 2021. 9. 20.

백준 20057 마법사 상어와 토네이도  - 삼성 SW 역량 테스트 기출

1. 문제 링크

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

 

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

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

www.acmicpc.net

 

2. 문제 해결에 대한 아이디어

1. 토네이도는 서 남 동 북 순으로 이동하며 각 방향으로 2턴 마다 이동거리가 길어진다. (1 1 2 2 3 3 4 4 ...)

2. 이동 방향에 따라 모래를 날리는 케이스가 4가지가 존재하므로 각각 구현했다.

   . Pair 클래스를 만들어 각 방향으로 움직일 때 모래를 날릴 위치를 배열로 표현했다.

   . 모래가 날릴 위치에 따른 비율을 저장하는 배열을 사용했다.

 

3. 격자를 넘어가는 모래는 outSand에 더해준다.

 

3. 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	static class Tor {
		int y, x, d;

		public Tor(int y, int x, int d) {
			super();
			this.y = y;
			this.x = x;
			this.d = d;
		}

	}

	static class Pair {
		int y, x;

		public Pair(int y, int x) {
			super();
			this.y = y;
			this.x = x;
		}

	}

	static int N;
	static int outSand = 0;
	static int[][] board;
	static int[] dirY = { 0, 1, 0, -1 };
	static int[] dirX = { -1, 0, 1, 0 };

	static double[] percent = { 0.05, 0.1, 0.1, 0.02, 0.07, 0.07, 0.02, 0.01, 0.01 };
	static Pair[] pairW = { new Pair(0, -2), new Pair(-1, -1), new Pair(1, -1), new Pair(-2, 0), new Pair(-1, 0),
			new Pair(1, 0), new Pair(2, 0), new Pair(-1, 1), new Pair(1, 1) };
	static Pair[] pairS = { new Pair(2, 0), new Pair(1, -1), new Pair(1, 1), new Pair(0, -2), new Pair(0, -1),
			new Pair(0, 1), new Pair(0, 2), new Pair(-1, -1), new Pair(-1, 1) };
	static Pair[] pairE = { new Pair(0, 2), new Pair(-1, 1), new Pair(1, 1), new Pair(-2, 0), new Pair(-1, 0),
			new Pair(1, 0), new Pair(2, 0), new Pair(-1, -1), new Pair(1, -1) };
	static Pair[] pairN = { new Pair(-2, 0), new Pair(-1, -1), new Pair(-1, 1), new Pair(0, -2), new Pair(0, -1),
			new Pair(0, 1), new Pair(0, 2), new Pair(1, -1), new Pair(1, 1) };
	static Tor tor;

	// 서남동북 으로 토네이도가 이동할 때, 날리는 모래를 각각 구현
	// 1 1 2 2 3 3 4 4 으로 토네이도가 같은 방향으로 이동
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String s = br.readLine();
		N = Integer.parseInt(s);
		board = new int[N][N];

		for (int i = 0; i < N; i++) {
			String[] line = br.readLine().split(" ");
			for (int j = 0; j < N; j++) {
				board[i][j] = Integer.parseInt(line[j]);
			}
		}

		tor = new Tor(N / 2, N / 2, 0);

		int loop = 1;
		int cnt = 0;
		while (true) {

			if (loop > N)
				break;

			for (int i = 0; i < loop; i++) {
				torMove();
				if (tor.y < 0 || tor.x < 0 || tor.y >= N || tor.x >= N)
					break;
				sandMove(tor.y, tor.x, tor.d, board[tor.y][tor.x]);
			}

			tor.d = (tor.d + 1) % 4;

			++cnt;
			if (cnt == 2) {
				cnt = 0;
				++loop;
			}

		}

		System.out.println(outSand);

	}

	static void torMove() {
		tor.y = tor.y + dirY[tor.d];
		tor.x = tor.x + dirX[tor.d];
	}

	static void sandMove(int y, int x, int dir, int sand) {
		// 방향에 따라 구현을 달리한다.
		int yy = 0, xx = 0, ss; // ss = sand
		int alpha = sand;
		for (int i = 0; i < 9; i++) {
			if (dir == 0) {
				yy = y + pairW[i].y;
				xx = x + pairW[i].x;
			} else if (dir == 1) { // 남
				yy = y + pairS[i].y;
				xx = x + pairS[i].x;
			} else if (dir == 2) { // 동
				yy = y + pairE[i].y;
				xx = x + pairE[i].x;
			} else if (dir == 3) { // 북
				yy = y + pairN[i].y;
				xx = x + pairN[i].x;
			}
			ss = (int) (sand * percent[i]);
			alpha -= ss;
			if (yy < 0 || xx < 0 || yy >= N || xx >= N) {
				outSand += ss;
				continue;
			}
			board[yy][xx] += ss;

		}
		yy = y + dirY[dir];
		xx = x + dirX[dir];
		if (yy < 0 || xx < 0 || yy >= N || xx >= N) {
			outSand += alpha;

		} else {
			board[yy][xx] += alpha;
		}

	}

}
 

4. 채점 결과

5. 느낀 점

1. alpha 위치에 날릴 모래를 따로 계산했는데 굳이 그럴 필요는 없었다.

2. 30분 동안 문제 분석을 먼저 하고 코딩을 했는데 실수가 줄어든 느낌이다.

3. 4 방향에 대한 배열을 구성할 때, 종이에 먼저 써보고 구성했다.

 

댓글