백준 17143 낚시왕 (Java,자바)

jonghyukLee·2021년 10월 29일
0

이번에 풀어본 문제는
백준 17143번 낚시왕 입니다.

📕 문제 링크

❗️코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

class Shark
{
    int x,y,dir,mv_cnt,size;

    public Shark(int x, int y, int mv_cnt, int dir, int size)
    {
        this.x = x;
        this.y = y;
        this.mv_cnt = mv_cnt;
        this.dir = dir;
        this.size = size;
    }

}
public class Main {
    static int answer;
    static PriorityQueue<Shark> sharks;
    static List<Shark> tmp_list;
    static int dead_x,dead_y;
    static int [][] map;
    static int R,C,M;
    static int [] dx = {0,-1,1,0,0}; // 상 하 우 좌
    static int [] dy = {0,0,0,1,-1};
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        R = Integer.parseInt(st.nextToken());
        C = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        map = new int[R+1][C+1];
        sharks = new PriorityQueue<>(new Comparator<Shark>() {
            @Override
            public int compare(Shark o1, Shark o2) {
                return o2.size - o1.size;
            }
        });


        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 s = Integer.parseInt(st.nextToken());
            int d = Integer.parseInt(st.nextToken());
            int z = Integer.parseInt(st.nextToken());

            map[r][c] = z;
            sharks.add(new Shark(r,c,s,d,z));
        }
        int fisherman = 0;
        while(fisherman++ < C)
        {
            dead_x = 0;
            dead_y = 0;
            for(int i = 1; i <= R; ++i) // 낚시
            {
                if(map[i][fisherman] > 0)
                {
                    answer += map[i][fisherman];
                    map[i][fisherman] = 0;
                    dead_x = i;
                    dead_y = fisherman;
                    break;
                }
            }
            map = new int[R+1][C+1];
            tmp_list = new ArrayList<>();
            move();
            sharks.clear();
            sharks.addAll(tmp_list);
        }
        System.out.print(answer);
    }
    static void move()
    {
        while(!sharks.isEmpty())
        {
            Shark cur = sharks.poll();
            if(cur.x == dead_x && cur.y == dead_y) continue; // 죽은 상어의 좌표일경우

            int mx = cur.x;
            int my = cur.y;
            int dir = cur.dir;
            for(int i = 0; i < cur.mv_cnt; ++i)
            {
                mx += dx[dir];
                my += dy[dir];

                if(!isValid(mx,my))
                {
                    dir = turn(dir);
                    i -= 2;
                }
            }
            if(map[mx][my] > 0) continue;
            map[mx][my] = cur.size;
            tmp_list.add(new Shark(mx,my,cur.mv_cnt,dir,cur.size));
        }

    }
    static int turn(int dir)
    {
        if(dir == 1) return 2;
        else if(dir == 2) return 1;
        else if(dir == 3) return 4;
        else if(dir == 4) return 3;
        else return 0; //default
    }
    static boolean isValid(int x, int y)
    {
        return x > 0 && y > 0 && x <= R && y <= C;
    }
}

📝 풀이

주어진 조건에 맞게 순차적으로 수행하는 구현 문제입니다.
map 배열은 해당 좌표에 존재하는 상어의 크기를 보관하며, 0보다 큰 값이 들어있을 경우 상어가 존재한다고 판단합니다. (2번 조건 수행을 위해 상어의 존재여부 판단 + 출력값 누적계산)
위를 이용하여 낚시꾼의 현재 위치의 열에서 map의 크기가 0보다 큰 값을 만났을 때, 그 상어를 사냥하고, answer값에 해당 map의 크기(상어의 크기)를 합해주고 빈칸으로 바꾼 후, 반복을 종료합니다.
저는 상어의 이동을 우선순위 큐를 활용했습니다. 같은 좌표에 여러마리의 상어가 존재한다면, 크기가 큰 상어가 다른 상어를 잡아먹는다는 조건을 고려하기 위함입니다. 사이즈가 큰 상어부터 먼저 이동을 수행한다면, 그 이후 이동한 상어는 무조건 그 상어보다 사이즈가 작을것이고(입력 조건에 크기가 같은상어는 없음) 이동이 끝나고 해당 위치에 이미 상어가 존재한다면(map의 값이 0 보다 클 때) 해당 상어의 이동을 종료합니다.
다음 이동을 위해 온전히 이동을 완수한 상어는 tmp_list에 담아두고, move함수를 종료한 시점에서 우선순위큐를 초기화하여 살아남은 상어들을 다시 add 해줍니다.

📜 후기

뭔가 상황이 그려져서 재밌게 풀었던 문제입니다. 난이도에 비해 수월하게 풀어서 기분이 좋았습니다 ㅎㅎ
문제추천: 영통변진우

profile
머무르지 않기!

0개의 댓글