It's easy, if you try

[백준/boj] 20056: 마법사 상어와 파이어볼(JAVA) / 구현 본문

알고리즘/자바(Java)

[백준/boj] 20056: 마법사 상어와 파이어볼(JAVA) / 구현

s5he2 2021. 10. 17. 14:59
반응형

문제

 

20056번: 마법사 상어와 파이어볼

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치

www.acmicpc.net

풀이

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

public class Main {
	static int[] dx = { -1, -1, 0, 1, 1, 1, 0, -1};
	static int[] dy = { 0, 1, 1, 1, 0, -1, -1, -1};
	static List<Ball>[][] map;
	static int N;

	static class Ball {
		int x, y, m, s, d; // cnt는 맵에 내가 몇번째인지.
		boolean isMoved;

		Ball(int x, int y, int m, int s, int d, boolean isMoved) {
			this.x = x;
			this.y = y;
			this.m = m;
			this.s = s;
			this.d = d;
			this.isMoved = isMoved;
		}

	}

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		N = Integer.parseInt(st.nextToken()); // 행, 열 크기
		int M = Integer.parseInt(st.nextToken()); // 파이어볼 개수
		int K = Integer.parseInt(st.nextToken()); // 명령 횟수

		map = new ArrayList[N][N];
		for(int i=0; i< N; i++) {
			for(int j=0; j<N; j++) {
				map[i][j] = new ArrayList<Ball>();
			}
		}

		for (int i = 1; i <= M; i++) { // 볼의 번호는 1~M
			st = new StringTokenizer(br.readLine());
			int x = Integer.parseInt(st.nextToken())-1; // 좌표가 1~N으로 주어지면 -1 하기!
			int y = Integer.parseInt(st.nextToken())-1;
			int m = Integer.parseInt(st.nextToken());
			int s = Integer.parseInt(st.nextToken());
			int d = Integer.parseInt(st.nextToken());
			Ball ball = new Ball(x, y, m, s, d, false);
			map[x][y].add(ball);
		}
		int cnt = 0;
		int answer = 0;
		while (cnt < K) {
			// 이동 // 시간줄이려면 if(move()true일때만 sumAndDivide)
			move();
			// 합치기
			sumAndDivide();
			// 0인 파이어볼 소멸
			answer = kill();
			cnt++;
		}
		
		System.out.println(answer);
	}

	private static int kill() {
		int sum = 0;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if(map[i][j].size() == 0) continue;
				int cnt = map[i][j].size();
				for(int c=cnt-1; c>=0; c--) {
					if(map[i][j].get(c).m == 0) map[i][j].remove(c);
					else {
						map[i][j].get(c).isMoved = false;
						sum += map[i][j].get(c).m;
					}
				} 
			}
		}
		return sum;
	}

	private static void sumAndDivide() {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (map[i][j].size() < 2)
					continue;
				// 2개 이상이면
				int size = map[i][j].size();
				int cnt = 0; // 파이어볼 개수
				int sumM = 0; // 질량 합
				int sumS = 0; // 속력 합
				boolean isEven = true; // 모든 방향이 짝수?
				boolean isOdd = true; // 모든 방향이 홀수?
				for (int c = size - 1; c >= 0; c--) {
					cnt++;
					sumM += map[i][j].get(c).m;
					sumS += map[i][j].get(c).s;
					if (map[i][j].get(c).d % 2 == 0) { // 방향이 짝수
						isOdd = false;
					} else { // 홀수
						isEven = false;
					}
				}

				map[i][j].clear();
				int newM = sumM / 5;
				int newS = sumS / cnt;
				// 모두 짝수인지 홀수인지
				if (isOdd || isEven) {
					map[i][j].add(new Ball(i, j, newM, newS, 0, false));
					map[i][j].add(new Ball(i, j, newM, newS, 2, false));
					map[i][j].add(new Ball(i, j, newM, newS, 4, false));
					map[i][j].add(new Ball(i, j, newM, newS, 6, false));
				} else {
					map[i][j].add(new Ball(i, j, newM, newS, 1, false));
					map[i][j].add(new Ball(i, j, newM, newS, 3, false));
					map[i][j].add(new Ball(i, j, newM, newS, 5, false));
					map[i][j].add(new Ball(i, j, newM, newS, 7, false));
				}
			}
		}
	}

	private static void move() {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if(map[i][j].size() == 0) continue;
				int cnt = map[i][j].size();
				for(int c = cnt-1; c>=0; c--) {
					if(map[i][j].get(c).isMoved) continue; // 이미 움직였던 볼이면 안움직임 
					Ball ball = map[i][j].get(c);
					map[i][j].remove(c);
					int x = ball.x;
					int y = ball.y;
					int nx = x, ny = y;
					for (int s = 0; s < ball.s; s++) { // 속력만큼 이동
						nx = x + dx[ball.d];
						ny = y + dy[ball.d];
						// 모든 벽은 이어져있음. 
						if(nx < 0) {
							nx = N -1;
						} else if(nx >= N) {
							nx = 0;
						} 
						if(ny >= N) {
							ny = 0;
						} else if(ny < 0) {
							ny = N -1;
						}
						x = nx;
						y = ny;
					}
					ball.x = x;
					ball.y = y;
					ball.isMoved = true;
					
					map[ball.x][ball.y].add(ball);
				}
			}
		}
	}
}
반응형
Comments