티스토리 뷰
문제 - (www.acmicpc.net/problem/19237)
🤔문제 접근 방법
상어마다 상하좌우 우선순위가 있네?->상어 클래스에 dir(현재 상어가 바라보는 방향), dirs(이 상어만의 우선순위)를 저장시켜 놓자
각 상어들 이동은 어떻게 하지?
- 다른 상어의 냄새가 없는 곳이 발견되면
- 그 위치로 이동한다
- 여기서 주의할 점!!! 그냥 이동하면 안 된다. tmp에 원래 map을 복사해놓고, tmp에다가 상어의 위치를 업데이트한다! 그랬을 때, 동시에 동일한 칸으로 이동하는 상어가 생긴다면, 상어의 숫자를 보고 판단하여 숫자가 가장 작은 상어만 이동시키고 나머지 상어는 모두 제거해준다. (반복문을 다 돌고 난 다음 제거작업 진행)
- 그 위치로 이동한다
- 상하좌우 모두에 상어의 냄새가 존재한다면
- 나의 우선순위 순서로 방문했을 때, 가장 먼저 발견된 나의 냄새가 있는 위치로 이동
📌주의할 점
- 개인적으로 까다로운 시뮬레이션 문제였다. 까다로울수록 설계단계에 시간을 많이 투자해서 꼼꼼하게 계획을 세운 뒤 코딩해야 한다...!! 이번에도 대충 설계한 뒤 코드로 바로 옮기는 바람에 디버깅하느라 시간을 너무 많이 뺏겼다. 주의하자.
코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
public class Main {
static int N, M, K;
static ArrayList<Shark> list;
static Point[][] map;
static int[] dy = { 0, -1, 1, 0, 0 };
static int[] dx = { 0, 0, 0, -1, 1 };
// 1, 2, 3, 4는 각각 위, 아래, 왼쪽, 오른쪽을 의미
static class Point {
int shark;
int k;
public Point(int shark, int k) {
this.shark = shark;
this.k = k;
}
}
static class Shark {
int num;
int y;
int x;
int dir;
int[][] dirs;
public Shark(int num, int y, int x) {
this.num = num;
this.y = y;
this.x = x;
this.dirs = new int[5][];
}
}
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()); // (2 ≤ N ≤ 20, 2 ≤ M ≤ N2, 1 ≤ k ≤ 1,000)
M = Integer.parseInt(st.nextToken()); // 상어 1~M 번호 붙여 있음
K = Integer.parseInt(st.nextToken());
list = new ArrayList<>();
map = new Point[N][N];// NxN map
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
int cur = Integer.parseInt(st.nextToken());
if (cur == 0) {
map[i][j] = new Point(0, 0);
} else {
list.add(new Shark(cur, i, j));
map[i][j] = new Point(cur, K);// 상어는 자신의 위치에 냄새 뿌림
}
}
}
list.sort((o1, o2) -> {
return Integer.compare(o1.num, o2.num);
});
// 상어의 처음 방향
st = new StringTokenizer(br.readLine());
for (int i = 0; i < M; i++) {
list.get(i).dir = Integer.parseInt(st.nextToken());
}
// 각 상어의 우선순위
for (int i = 0; i < M; i++) {// M개 칸에 상어 한마리씩 존재
for (int j = 1; j <= 4; j++) {
st = new StringTokenizer(br.readLine());
list.get(i).dirs[j] = new int[] { 0, Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()),
Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()) };
}
}
System.out.println(simulate());// 1번 상어만 격자에 남게 되기까지 몇 초가 걸리는지를 구하는 프로그램
// 상어1 가장 강력해서 모두 쫓아냄
// k번 이동 시 냄새 사라짐
}
private static int simulate() {
int timer = 0;
while (list.size() > 1) {
// printMap();
if(timer >= 1000) return -1;
// 매 초마다 tmp 맵이 필요함
Point[][] tmp = deepCopy(map);
int size = list.size();
ArrayList<Integer> removeShark = new ArrayList<>();
loop: for (int i = 0; i < size; i++) {
Shark shark = list.get(i);
int sharkNum = shark.num;
int y = shark.y;
int x = shark.x;
int dir = shark.dir;
int[][] dirs = shark.dirs;
// 1초 후 상하좌우 하나로 이동
int my = -1;
int mx = -1;
int md = -1;
boolean find = false;
for (int d = 1; d <= 4; d++) {
int ny = y + dy[dirs[dir][d]];
int nx = x + dx[dirs[dir][d]];
if (ny < 0 || nx < 0 || ny >= N || nx >= N) // 맵 밖으로 벗어나면 컨티뉴
continue;
// 상어 이동 방향 결정 시, 먼저 인접한 칸 중 아무 냄새 없는 칸 이동
if (map[ny][nx].k == 0) { // 아무 냄새 없는 칸이면 바로 이동
// 가능한 칸 여러개 일 시,특정한 우선순위 존재. 상어마다 다름. 상어가 보는 방향에 따라 다름.
if (tmp[ny][nx].k != 0) { // 한 칸에 여러마리 있으면 가장 작은 번호만남음
if (tmp[ny][nx].shark > sharkNum) {
removeShark.add(tmp[ny][nx].shark);// 원래 tmp 에 있던 상어 쫓겨남
shark.dir = dirs[dir][d]; // 이동한 방향이 보고있는 방향이 됨
shark.y = ny; // 상어 위치 이동
shark.x = nx;
tmp[ny][nx].shark = sharkNum;
tmp[ny][nx].k = K + 1;
} else {
removeShark.add(sharkNum);// 지금 상어 쫓겨남
}
} else { // 비어있다면 이동시킴
shark.dir = dirs[dir][d]; // 이동한 방향이 보고있는 방향이 됨
shark.y = ny; // 상어 위치 이동
shark.x = nx;
tmp[ny][nx].shark = sharkNum;
tmp[ny][nx].k = K + 1;
}
continue loop;
} else if (!find && map[ny][nx].shark == sharkNum) {
my = ny;
mx = nx;
md = d;
find = true; // 가장 처음 발견된 나의 냄새가 있던 곳을 기록하기 위한 플래그
}
}
// 아무 냄새 없는 칸이 없었다면 자신의 냄새가 있던 칸으로 이동
shark.dir = dirs[dir][md];
shark.y = my;
shark.x = mx;
tmp[my][mx].k = K + 1;
} // end of for
// map 업데이트
map = tmp;
// map의 시간 k값 모두 1씩 내림
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j].k > 0)
map[i][j].k--;
else
map[i][j].k = 0;
}
}
// 쫓겨난 상어 제거
for (int i = 0; i < removeShark.size(); i++) {
int cur = removeShark.get(i);
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Shark shark = (Shark) iterator.next();
if (shark.num == cur) {
iterator.remove();
continue;
}
}
}
timer++;
}
return timer;
}
private static void printMap() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print("[" + map[i][j].shark + "," + map[i][j].k + "]");
}
System.out.println();
}
System.out.println("---------------------");
}
private static Point[][] deepCopy(Point[][] origin) {
Point[][] ret = new Point[N][N];
for (int i = 0; i < origin.length; i++) {
for (int j = 0; j < origin[i].length; j++) {
ret[i][j] = new Point(origin[i][j].shark, origin[i][j].k);
}
}
return ret;
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 19238번 / Java / 스타트 택시 (0) | 2020.09.19 |
---|---|
[백준] 4485번 / Java / 녹색 옷 입은 애가 젤다지? (0) | 2020.09.06 |
[백준] 1261번 / Java / 알고스팟 (0) | 2020.09.05 |
[백준] 18513번 / Java / 샘터 (0) | 2020.09.05 |
[백준] 3109번 / Java / 빵집 (0) | 2020.08.27 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 배열순회
- 사다리 조작
- 재귀
- 코딩테스트 연습
- 그리디
- 완전탐색
- 구현
- 시뮬레이션
- BOJ
- 톱니바퀴
- Access-Control-Allow-Origin
- 16234
- withCredentials
- 14891
- 아기상어
- java
- 큰 수 만들기
- 우선순위큐
- 브라우저 요청
- 인구이동
- dfs
- Greedy
- header
- 코테
- 자바
- 코딩테스트
- 백준
- 드래곤 커브
- 구명보트
- 프로그래머스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함