본문 바로가기

알고리즘/구현

자바 | 백준 | 20056 | 마법사 상어와 파이어볼

Solution

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

public class Main {

	static int N, M, K;
	static int[] dx = { -1, -1, 0, 1, 1, 1, 0, -1 };
	static int[] dy = { 0, 1, 1, 1, 0, -1, -1, -1 };
	static List<List<List<FireBall>>> list;

	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());
		K = Integer.parseInt(st.nextToken());

		list = new ArrayList<>();
		for (int i = 0; i <= N; i++) {
			list.add(new ArrayList<>());
			for (int j = 0; j <= N; j++) {
				list.get(i).add(new ArrayList<>());
			}
		}

		for (int i = 0; i < M; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			int r = Integer.parseInt(st.nextToken());
			int c = Integer.parseInt(st.nextToken());
			int m = Integer.parseInt(st.nextToken());
			int s = Integer.parseInt(st.nextToken());
			int d = Integer.parseInt(st.nextToken());
			list.get(r).get(c).add(new FireBall(r, c, m, s, d));
		}

		while (K-- > 0) {
			func1();
			func2();
		}

		System.out.println(getSum());
	}

	static int getSum() {
		int sum = 0;
		for (int i = 0; i <= N; i++) {
			for (int j = 0; j <= N; j++) {
				for (int k = 0; k < list.get(i).get(j).size(); k++) {
					sum += list.get(i).get(j).get(k).m;
				}
			}
		}
		return sum;
	}

	static void func1() {
		ArrayList<FireBall> moveFireBalls = new ArrayList<>();
		for (int i = 0; i <= N; i++) {
			for (int j = 0; j <= N; j++) {
				for (int k = 0; k < list.get(i).get(j).size(); k++) {
					FireBall temp = list.get(i).get(j).get(k);
					int nx = temp.r + (dx[temp.d] * temp.s) % N;
					int ny = temp.c + (dy[temp.d] * temp.s) % N;
					if (nx < 1) {
						nx += N;
					} else if (nx > N) {
						nx -= N;
					}
					if (ny < 1) {
						ny += N;
					} else if (ny > N) {
						ny -= N;
					}
					list.get(i).get(j).remove(k);
					k--; // 현재 위치에서 삭제
					temp.r = nx;
					temp.c = ny;
					moveFireBalls.add(temp);
				}
			}
		}

		for (int i = 0, size = moveFireBalls.size(); i < size; i++) {
			FireBall temp = moveFireBalls.get(i);
			list.get(temp.r).get(temp.c).add(temp);
		}
	}

	static void func2() {
		for (int i = 0; i <= N; i++) {
			for (int j = 0; j <= N; j++) {
				int size = list.get(i).get(j).size();
				if (size > 1) {
					int mSum = 0;
					int sSum = 0;
					boolean oddDir = true;
					boolean evenDir = true;
					for (int k = 0; k < size; k++) {
						mSum += list.get(i).get(j).get(k).m;
						sSum += list.get(i).get(j).get(k).s;
						if (list.get(i).get(j).get(k).d % 2 == 1) {
							evenDir = false;
						} else {
							oddDir = false;
						}
					}

					list.get(i).get(j).clear();
					int m = mSum / 5;
					int s = sSum / size;
					if (m != 0) { // 질량이 0인 파이어볼은 없어짐
						if (evenDir || oddDir) { // 모두 짝수이거나 모두 홀수
							for (int dir = 0; dir < 8; dir += 2) {
								list.get(i).get(j).add(new FireBall(i, j, m, s, dir));
							}
						} else {
							for (int dir = 1; dir < 8; dir += 2) {
								list.get(i).get(j).add(new FireBall(i, j, m, s, dir));
							}
						}
					}
				}
			}
		}
	}

	static class FireBall {
		int r;
		int c;
		int m;
		int s;
		int d;

		FireBall(int r, int c, int m, int s, int d) {
			this.r = r;
			this.c = c;
			this.m = m;
			this.s = s;
			this.d = d;
		}

		FireBall(int m, int s, int d) {
			this.m = m;
			this.s = s;
			this.d = d;
		}

		public String toString() {
			return "(" + m + ", " + s + ", " + d + ")";
		}
	}
}

 

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

 

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

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

www.acmicpc.net