이번에 풀어본 문제는
백준 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 해줍니다.
뭔가 상황이 그려져서 재밌게 풀었던 문제입니다. 난이도에 비해 수월하게 풀어서 기분이 좋았습니다 ㅎㅎ
문제추천: 영통변진우