[BOJ] 20056. 마법사 상어와 파이어볼

2021. 9. 18. 19:40알고리즘/백준 문제 풀이

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

접근 방법

구현 문제는 대부분 데이터를 어떻게 저장하는지에 따라 풀이가 달라진다. (제일 중요)

격자의 맵에서 데이터를 어떻게 담아줘야 할 지 생각을 했고

파이어볼2차 배열을 생각하였다.

LinkedList<Fire>[][] map = new LinkedList[N][N];
// 이렇게 할 경우 x,y에 대해 Fire 정보를 모두 가져올수 있기 때문이다.

또한, move를 해주게 될 때 map은 새로운 map이 되기 때문에 move를 해준 후 다시 추가를 해줘야한다.

static void move(){

        List<Fire> next[][] = new LinkedList[N][N];
        for(int i = 0; i < N; i++) {
            for (int k = 0; k < N; k++) {
                next[i][k] = new LinkedList<>();
            }
        }
        ... move end ...
        map = next;
}

주의사항

격자의 행과 열은 1번부터 N번까지 번호가 매겨져 있고, 1번 행은 N번과 연결되어 있고, 1번 열은 N번 열과 연결 ! 이 부분을 생각해야한다.

Need Know

  1. 구현

전체 코드 ( Java )

import javax.swing.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

class Main{
    // 1번부터 N번까지 번호가 매겨져 있고, 1번 행은 N번과 연결되어 있고, 1번 열은 N번 열과
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static int N;
    static int M;
    static int K;
    static List<Fire>[][] map;
    static int[] dx = {-1,-1,0,1,1,1,0,-1};
    static int[] dy = {0,1,1,1,0,-1,-1,-1};
    public static void main(String[] args) throws IOException {
        set();
        solve();
    }
    static void set() throws IOException {
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        map = new LinkedList[N][N];
        for(int i = 0; i < N; i++) {
            for (int k = 0; k < N; k++) {
                map[i][k] = new LinkedList<>();
            }
        }
        for(int i=0; i<M; i++){
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken())-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());
            map[x][y].add(new Fire(m,d,s));
        }
    }
    static void solve(){
        for(int i=0; i<K; i++){
            move();
        }
        int answer = 0;
        for(int i = 0; i < N; i++) {
            for(int k = 0; k < N; k++){
                for(Fire fire : map[i][k])
                    answer += fire.m;
            }
        }
        System.out.println(answer);
    }
    static void move(){

        List<Fire> next[][] = new LinkedList[N][N];
        for(int i = 0; i < N; i++) {
            for (int k = 0; k < N; k++) {
                next[i][k] = new LinkedList<>();
            }
        }
        for(int i=0; i<N; i++){
            for(int k=0; k<N; k++){
                if(map[i][k].size() > 0){
                    for(Fire fire : map[i][k]){
                        int dis = fire.s % N;
//                        System.out.println(i +" , " + k);
                        int nx = i + (dx[fire.d]*dis);
                        int ny = k + (dy[fire.d]*dis);
                        if(nx >= N) nx -= N;
                        else if(nx < 0) nx += N;
                        if(ny >= N) ny -= N;
                        else if(ny<0) ny += N;
//                        System.out.println(nx +" , " + ny + " ->"+fire.m);
                        next[nx][ny].add(new Fire(fire.m,fire.d,fire.s));
                    }
                }
            }
        }
        map = next;
        combine();
    }
    static void combine(){
        for(int i=0; i<N; i++){
            for(int k=0; k<N; k++){
                if(map[i][k].size() > 1){
                    int mSum = 0;
                    int sSum = 0;
                    boolean even = true, odd = true;
                    for(Fire fire : map[i][k]){
                        mSum += fire.m;
                        sSum += fire.s;
                        if(fire.d % 2 == 0){
                            odd = false;
                        }else{
                            even = false;
                        }
                    }
                    int newMSum = mSum / 5;
                    int newSSum = sSum / map[i][k].size();
                    map[i][k] = new LinkedList<>();

                    if(newMSum > 0){
                        for(int z=0; z<4; z++){
                            if(odd || even){
                                map[i][k].add(new Fire(newMSum, 2 * z, newSSum));
                            }else{
                                map[i][k].add(new Fire(newMSum, 1 + 2 * z, newSSum));
                            }
                        }
                    }
                }
            }
        }
    }
}
class Fire{
    int m,d,s; // 질량 방향 속력

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

'알고리즘 > 백준 문제 풀이' 카테고리의 다른 글

[BOJ] 2174. 로봇 시뮬레이션  (0) 2021.09.19
[BOJ] 10800. 컬러볼  (0) 2021.09.18
[BOJ] 1182. 부분수열의 합  (0) 2021.04.21
[BOJ] 2573. 빙산  (0) 2021.03.26
[BOJ] 2178. 미로 탐색  (0) 2021.03.16