티스토리 뷰

1. 문제

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

 

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

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

www.acmicpc.net


 

2. 문제 풀이 겸 회고

구현 넘 재밌는데..... 와... 이번에 파이어볼 방향 별로 옮겨줄 때 애먹었다...(시뮬 미워..) ㅜ0ㅜ 

그 부분만 아니면 1시간 컷 했을 듯.... ;-;

[문제 설명]

문제를 보면 파이어볼 옮겨서 파이어볼 분해되고 합치고 이런 과정이 반복된다.

시뮬(반복해서 돌려주고) 과 구현(조건에 맞춰 구현)의 조합 

문제의 파이어볼 위치값 이동부분이다.

이부분에서 한 3시간 날려먹은 듯... 시롸냐....

0 1 2 3 0 1 2 3 0 1 2 3 (이런 식으로 맵 index가 연달아 있음 -> 행, 열 둘 다)

처음에는 그냥 case 문으로 하나씩 조건에 맞춰서 넣어주려고 했다.. 하지만 이건 너무 반복되는 부분도 많고 그래서 지웠다. 

또한... 계속 IndexOutOfBoundsException 나고.. 막 값이 이상한 데에 들어가고 그래서 방향 탐색으로 해줬다.

 

static int[] dr = { -1, -1, 0, 1, 1, 1, 0, -1 };
static int[] dc = { 0, 1, 1, 1, 0, -1, -1, -1 };

0~7번까지 방향을 의미한다.

int nr = cur.r + (dr[cur.d] * cur.s) % N;
int nc = cur.c + (dc[cur.d] * cur.s) % N;

이건 다음에 넣어줘야 할 파이어볼 위치를 구해줬다.
(여기서 cur은 Fireball의 정보가 담긴 객체를 의미하며, r과 c는 0부터 해주기 위해 맨 처음에 -1을 해줬음)

하지만 이렇게만 할 경우, nr, nc가 0보다 작거나 N-1보다 클 경우 IndexOutOfBoundsException 이놈이 나온다.

그래서 조건 추가!

if (nr < 0) {
	nr = N + nr;
} else if (nr >= N) {
	nr %= N;
}
if (nc < 0) {
	nc = N + nc;
} else if (nc >= N) {
	nc %= N;
}

이렇게 해줘서 방향 옮겨줬다. 

또한, 여기서 바로 빼왔던 2차원배열에 바로 삽입하는 게 아니라 객체 list 하나 선언해서 그 안에 임시 보관해줬음

fbList.add(new Fireball(nr, nc, cur.m, cur.s, cur.d));

 다 구해주면

임시 보관된 객체들 다시 2차원배열에 삽입시켜줌!

이렇게 Fireball 움직여주고, 그 후는 문제에서 원하는 조건으로 구현해줬음 

각 위치에 있는 파이어볼 하나로 합친 다음에 질량이 5보다 작으면 (질량 / 5 =질량 0) 해당 구역은 pass 하고 

클 경우에는 파이어볼 4개로 나눠서 (조건에 맞춰서) 넣어줬음

 

그럼 끗!

아마 많은 분들이 저기 파이어볼 이동 과정에서 애먹었을 듯 (나만 그럴 수도 ㅋㄷㅋㄷ)

 

 

3. 코드

package net.acmicpc.samsung;

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

public class Solution_20056_마법사상어와파이어볼 {
	static class Fireball {

		int r; // 행위치
		int c; // 열위치
		int m; // 질량
		int s; // 속력
		int d; // 방향

		public 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;

		}

	}

	static int N, M, K;
	static ArrayList<Fireball> map[][];
	static ArrayList<Fireball> fbList;

	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()); // M개의 파이어볼 정보
		K = Integer.parseInt(st.nextToken()); // K번 명령

		map = new ArrayList[N][N];
		for (int r = 0; r < N; r++) {
			for (int c = 0; c < N; c++) {
				map[r][c] = new ArrayList<Fireball>();

			}

		}

		for (int i = 0; i < M; i++) {
			st = new StringTokenizer(br.readLine());
			int r = Integer.parseInt(st.nextToken()) - 1;
			int c = Integer.parseInt(st.nextToken()) - 1;

			map[r][c].add(new Fireball(r, c, Integer.parseInt(st.nextToken()), 
            			Integer.parseInt(st.nextToken()),Integer.parseInt(st.nextToken())));
		}

		while (K-- > 0) {
			moveFireball();
		}
		int answer = 0;

		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				for (int k = 0; k < map[i][j].size(); k++) {
					answer += map[i][j].get(k).m;

				}

			}
		}
		System.out.println(answer);

	}

	private static void moveFireball() {
		fbList = new ArrayList<>();

		for (int r = 0; r < N; r++) {
			for (int c = 0; c < N; c++) {

				while (map[r][c].size() != 0) {
					Fireball cur = map[r][c].remove(0);
					selectDir(cur);
				}
			}
		}

		addMap(fbList);
		divFireball();

	}

	static int[] dr = { -1, -1, 0, 1, 1, 1, 0, -1 };
	static int[] dc = { 0, 1, 1, 1, 0, -1, -1, -1 };

	private static void selectDir(Fireball cur) {
		int nr = cur.r + (dr[cur.d] * cur.s) % N;
		int nc = cur.c + (dc[cur.d] * cur.s) % N;
//		System.out.println("====================");
//		System.out.println(cur.r + " " + cur.c + " " + cur.d + " " + cur.s);
//		System.out.println(nr + " " + nc);

		if (nr < 0) {
			nr = N + nr;
		} else if (nr >= N) {
			nr %= N;
		}
		if (nc < 0) {
			nc = N + nc;
		} else if (nc >= N) {
			nc %= N;
		}
		fbList.add(new Fireball(nr, nc, cur.m, cur.s, cur.d));

	}

	private static void addMap(ArrayList<Fireball> tmpList) {
		for (int i = 0; i < tmpList.size(); i++) {
			Fireball cur = tmpList.get(i);
			map[cur.r][cur.c].add(new Fireball(cur.r, cur.c, cur.m, cur.s, cur.d));
		}

	}

	private static void divFireball() {
		fbList = new ArrayList<>();

		for (int r = 0; r < N; r++) {
			for (int c = 0; c < N; c++) {
				if (map[r][c].size() >= 2) {
					int nm = 0; // 그 다음 질량
					int ns = 0; // 그 다음 속도
					int odd = 0; // 홀수 개수(방향)
					int even = 0; // 짝수 개수(방향)
					int len = map[r][c].size();
					while (map[r][c].size() != 0) {
						Fireball fb = map[r][c].remove(0);
						nm += fb.m;
						ns += fb.s;
						if (fb.d % 2 == 0) {
							even++;
						} else {
							odd++;
						}
					}
					
					if (nm < 5)
						continue;
					else {
						ns = ns / len;
						if (even == len || odd == len) {
							for (int i = 0; i < 4; i++) {
								fbList.add(new Fireball(r, c, nm / 5, ns, i * 2));
							}
						} else {
							for (int i = 0; i < 4; i++) {
								fbList.add(new Fireball(r, c, nm / 5, ns, i * 2 + 1));
							}
						}

					}

				}

			}
		}
		addMap(fbList);
	}

//현재 맵 객체 궁금하시면, 주석 풀고 원하는 위치에 메서드 삽입해서 사용하세용~
//	private static void print() {
//		for (int i = 0; i < map.length; i++) {
//			for (int j = 0; j < map[0].length; j++) {
//				System.out.print(i + " " + j + ": ");
//				for (int k = 0; k < map[i][j].size(); k++) {
//					System.out.print(map[i][j].get(k).m + " ");
//				}
//				System.out.println();
//			}
//			System.out.println();
//		}
//	}
}

 

 

피드백은 언제나 환영입니다 :) 🌳

댓글