-
20056. 마법사 상어와 파이어볼알고리즘/백준 2022. 9. 18. 16:35
https://www.acmicpc.net/problem/20056
조건 사항
- 마법사 상어가 크기가 N×N인 격자에 파이어볼 M개를 발사했다.
- 가장 처음에 파이어볼은 각자 위치에서 이동을 대기하고 있다.
- i번 파이어볼의 위치는 (ri, ci), 질량은 mi이고, 방향은 di, 속력은 si이다. 위치 (r, c)는 r행 c열을 의미한다.
- 격자의 행과 열은 1번부터 N번까지 번호가 매겨져 있고, 1번 행은 N번과 연결되어 있고, 1번 열은 N번 열과 연결되어 있다.
파이어볼의 방향은 어떤 칸과 인접한 8개의 칸의 방향을 의미하며, 정수로는 다음과 같다.
7 0 1 6 2 5 4 3 구현 사항
- 모든 파이어볼이 자신의 방향 di로 속력 si칸 만큼 이동한다.
- 이동하는 중에는 같은 칸에 여러 개의 파이어볼이 있을 수도 있다.
- 이동이 모두 끝난 뒤, 2개 이상의 파이어볼이 있는 칸에서는 다음과 같은 일이 일어난다.
- 같은 칸에 있는 파이어볼은 모두 하나로 합쳐진다.
- 파이어볼은 4개의 파이어볼로 나누어진다.
- 나누어진 파이어볼의 질량, 속력, 방향은 다음과 같다.
- 질량은 ⌊(합쳐진 파이어볼 질량의 합)/5⌋이다.
- 속력은 ⌊(합쳐진 파이어볼 속력의 합)/(합쳐진 파이어볼의 개수)⌋이다.
- 합쳐지는 파이어볼의 방향이 모두 홀수이거나 모두 짝수이면, 방향은 0, 2, 4, 6이 되고, 그렇지 않으면 1, 3, 5, 7이 된다.
- 질량이 0인 파이어볼은 소멸되어 없어진다.
마법사 상어가 이동을 K번 명령한 후, 남아있는 파이어볼 질량의 합을 구해보자.
입력
첫째 줄에 N, M, K가 주어진다.
둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다.
서로 다른 두 파이어볼의 위치가 같은 경우는 입력으로 주어지지 않는다.
출력
마법사 상어가 이동을 K번 명령한 후, 남아있는 파이어볼 질량의 합을 출력한다.
제한
- 4 ≤ N ≤ 50
- 0 ≤ M ≤ N2
- 1 ≤ K ≤ 1,000
- 1 ≤ ri, ci ≤ N
- 1 ≤ mi ≤ 1,000
- 1 ≤ si ≤ 1,000
- 0 ≤ di ≤ 7
LOGIC
1. 파이어볼의 다양한 정보를 담기위해 파이어볼 클래스를 구현하여 객체를 만들었습니다.
2. 해당 좌표에서의 비교를 위해 equals()를 재정의 하여 (r, c)를 비교하였습니다.
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.StringTokenizer; /** * 백준 20056. 마법사 상어와 파이어볼 - 골드 4 * @category 구현 */ public class Main { static int N, M, K, map[][]; static int[][] del = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}}; static ArrayList<FireBall> fireBall = new ArrayList<>(); /** * 파이어볼의 정보와 좌표 비교를 위한 클래스 */ static class FireBall { int r, c; int m , s, 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; } public FireBall(int r, int c) { this.r = r; this.c = c; } @Override public boolean equals(Object obj) { FireBall f = (FireBall) obj; return r == f.r && c == f.c; } } 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()); M = Integer.parseInt(st.nextToken()); K = Integer.parseInt(st.nextToken()); 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()); fireBall.add(new FireBall(r, c, m, s, d)); } for (int i = 0; i < K; i++) { move(); } int sum = 0; for(FireBall f : fireBall) sum += f.m; System.out.println(sum); } private static void move() { map = new int[N+1][N+1]; //이돟하기 전 매번 map 초기화 //이동 for (int i = 0, size = fireBall.size(); i < size; i++) { int r = fireBall.get(i).r; int c = fireBall.get(i).c; int dir = fireBall.get(i).d; int dist = fireBall.get(i).s % N; r += del[dir][0] * dist; c += del[dir][1] * dist; r = r<=0 ? N+r : (r>N ? r-N : r); c = c<=0 ? N+c : (c>N ? c-N : c); fireBall.get(i).r = r; fireBall.get(i).c = c; map[r][c]++; } //파이어볼 2개 이상인 곳 검사 for (int i = 1; i <= N; i++) { for (int j = 1; j <= N; j++) { if(map[i][j] > 1) { FireBall f = new FireBall(i, j); //비교를 위한 해당 좌표의 임시 파이어볼 생성 int m = 0, s = 0, cnt = 0; int[] d = new int[4]; boolean even = true, odd = true; //짝, 홀 for (int k = fireBall.size()-1; k >= 0; k--) { if(fireBall.get(k).equals(f)) { //해당 좌표의 파이어볼 //합치는 과정.. FireBall fb = fireBall.remove(k); m += fb.m; s += fb.s; cnt++; //짝수 검사 if(fb.d % 2 != 0) even = false; //홀수 검사 if(fb.d % 2 == 0) odd = false; } } //파이어볼 나누기 m = m/5; s = s/cnt; for (int k = 0; k < 4; k++) { d[k] = (even || odd) ? k*2 : k*2 + 1; //홀수 또는 짝수일 경우와 아닐 경우 } if(m != 0) { //질량이 0인 파이어볼은 소멸 for (int k = 0; k < 4; k++) { fireBall.add(new FireBall(i, j, m, s, d[k])); } } } } } } }
위 코드는 map 전체를 계속 탐색하기 때문에 실행 시간이 많이 나올겁니다.
이동한 곳의 좌표를 따로 저장하면 해결할 수 있을거 같고
지금보니 합칠 수 있는 부분도 보이고 조금 부족한 코드 같지만 통과했으니 넘어가겠습니다ㅎㅎ;;
'알고리즘 > 백준' 카테고리의 다른 글
9370. 미확인 도착지 (0) 2022.10.06 2887. 행성 터널 (0) 2022.10.02 5557. 1학년 (0) 2022.09.25 1644. 소수의 연속합 (2) 2022.09.22 21609. 상어 중학교 (0) 2022.09.18