❓ 문제 - 백준 어른 상어 19237번 - JAVA 풀이법
출처
(https://www.acmicpc.net/problem/19237)
📝 문제해결법
1. 이 문제는 구현로 풀었다.
- map이라는 2차원 배열에 상어의 번호를 저장한다.
- Node[]라는 객체 배열로 각 상어에 인덱스에 맞는 상어의 정보(위치 x, y, 방향 dir)를 저장한다.
- Smell이라는 2차원 객체로 어떤 상어가 냄새를 남겼는지, 그리고 남긴 시점은 언제인지를 체크 저장한다.
- shark_dir이라는 3차원 배열로 각 방향에 맞춰 방향의 우선순위를 저장한다.
- check() 메소드를 통해 격자 안에 1번의 상어만 남았는지 체크한다.
- 상어의 움직임에서 처음에 각 상어의 이동이 시작되면 방향을 우선순위에 맞춰 정하고 해당 방향으로 이동했을 때 만약 상어가 존재하지 않는 곳이라면 해당 상어의 정보를 남김 처리하고, 이미 존재한 곳이라면 상어의 숫자를 비교해서 더 작은 숫자를 가진 상어만 남고 나머지는 격자밖으로 쫓겨남 처리를 한다.
- 방향을 정할 때 첫 번째로 자기 방향에 맞는 우선순위를 토대로 냄새가 존재하지 않는 방향을 찾고, 만약 못 찾으면 자기 냄새가 있는 곳을 찾아서 해당 방향으로 선정한다.
- 냄새에 대한 처리는 냄새를 k초 뒤에 제거 처리하는 게 아니라 smell이라는 위치에 상어의 번호와 해당 시점을 기록하고 냄새가 존재하는지 여부를 따질 때 해당 냄새에 기록된 시점+k가 현재 시점보다 작을 경우 냄새가 제거된 것으로 맞춰서 구현한다.
💻 소스코드
// BOJ - 어른 상어(19237번)
// 구현
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main_19237 {
	public static int n, m, k;
	public static int[][] map;
	public static class Node {
		int x;
		int y;
		int dir;
		public Node(int x, int y) {
			this.x = x;
			this.y = y;
		}
		public Node(int x, int y, int dir) {
			this.x = x;
			this.y = y;
			this.dir = dir;
		}
	}
	
	public static class Smell {
		int num;
		int time;
		public Smell(int num, int time) {
			this.num = num;
			this.time = time;
		}
	}
	public static Node[] shark;
	public static int[] dx = {-1, 1, 0, 0};
	public static int[] dy = {0, 0, -1, 1};
	public static int[][][] shark_dir;
	public static Smell[][] smell;
	public static void main(String[] args) throws IOException {
		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());
		map = new int[n][n];
		smell = new Smell[n][n];
		shark = new Node[m+1];
		shark_dir = new int[m+1][4][4];
		
		for(int i=0;i<n;i++) {
			st = new StringTokenizer(br.readLine(), " ");
			for(int j=0;j<n;j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
				if(map[i][j] != 0) {
					shark[map[i][j]] = new Node(i, j);
					smell[i][j] = new Smell(map[i][j], k);
				}
			}
		}
		
		st = new StringTokenizer(br.readLine(), " ");
		for(int i=1;i<=m;i++) {
			shark[i].dir = Integer.parseInt(st.nextToken())-1;
		}
		
		// 상어들의 방향 우선순위 받기
		for(int s=1;s<=m;s++) {
			for(int i=0;i<4;i++) {
				st = new StringTokenizer(br.readLine(), " ");
				for(int j=0;j<4;j++) {
					shark_dir[s][i][j] = Integer.parseInt(st.nextToken()) -1;
				}
			}
		}
	
		int time = 0;
		while(time <= 1000) {
			if(check()) {
				break;
			}
			time++;
			// 상어의 이동 시작
			for(int s=1;s<=m;s++) {
				
				if(shark[s] == null) continue;
				Node node = shark[s];
				int d = node.dir;
				boolean check = false;
				// 냄새 없는 방향 잡기
				for(int i=0;i<4;i++) {
					int dir = shark_dir[s][d][i];
					int nx = node.x + dx[dir];
					int ny = node.y + dy[dir];
					if(0 <= nx && nx < n && 0 <= ny && ny < n) {
						if((smell[nx][ny] == null) || (smell[nx][ny].time < time)) {
							// 이동
							d = dir;
							check = true;
							break;
						}
					}
				}
				// 방향 못 찾음 -> 자기 냄새 있는 곳 찾기
				if(!check) {
					for(int i=0;i<4;i++) {
						int dir = shark_dir[s][d][i];
						int nx = node.x + dx[dir];
						int ny = node.y + dy[dir];
						if(0 <= nx && nx < n && 0 <= ny && ny < n) {
							if(smell[nx][ny].num == s) {
								// 이동
								d = dir;
								break;
							}
						}
					}
				}
				
				
				int nx = node.x + dx[d];
				int ny = node.y + dy[d];
				node.dir = d;
			
				if(map[nx][ny] == 0) {
					map[nx][ny] = s;
					map[node.x][node.y] = 0;
					shark[s].x = nx;
					shark[s].y = ny;
				} else if(map[nx][ny] > s){
					int delete = map[nx][ny];
					shark[delete] = null;
					map[nx][ny] = s;
					map[node.x][node.y] = 0;
					shark[s].x = nx;
					shark[s].y = ny;
				} else {
					shark[s] = null;
					map[node.x][node.y] = 0;
				}
				
				
				
			
			}
			
			// 냄새 뿌리기
			for(int s=1;s<=m;s++) {
				if(shark[s] != null) {
					smell[shark[s].x][shark[s].y] = new Smell(s, k+time);
				}
			}
		}
		
		System.out.println(time>1000?-1:time);
	}
	public static void print() {
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				System.out.print(map[i][j] +" ");
			}
			System.out.println();
		}
		System.out.println();
	}
	public static boolean check() {
		for(int i=2;i<=m;i++) {
			if(shark[i] != null) {
				return false;
			}
		}
		return true;
	}
}'알고리즘 > 알고리즘문풀' 카테고리의 다른 글
| BOJ - 컨베이어 벨트 위의 로봇 20055번 (JAVA) (0) | 2022.04.30 | 
|---|---|
| BOJ - 스타트택시 19238번 (JAVA) (0) | 2022.04.30 | 
| BOJ - 청소년 상어 19236번 (JAVA) (0) | 2022.04.30 | 
| BOJ - 모노미노도미노2 20061번 (JAVA) (0) | 2022.04.30 | 
| BOJ - 원판 돌리기 17822번 (JAVA) (0) | 2022.04.30 |