[SWEA] 1953. 탈주범 검거

BFS를 이용한 나의 풀이

  • 메모리 : 26,332 KB
  • 실행시간 : 126 ms
  • 코드길이 : 3,594 B
  • 소요시간 : 1H 10M
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Solution_1953_탈주범검거 {

	static int N, M, R, C, L, ans;
	static Queue<Point> queue;
	static boolean[][] visited;
	static int[][] map;
	static int[][] delta = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } };
	
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder answer = new StringBuilder();
		StringTokenizer st = null;
		int T = Integer.parseInt(in.readLine());
		for (int tc = 1; tc <= T; tc++) {
			st = new StringTokenizer(in.readLine()," ");
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			R = Integer.parseInt(st.nextToken());
			C = Integer.parseInt(st.nextToken());
			L = Integer.parseInt(st.nextToken());
			map = new int[N][M];
			visited = new boolean[N][M];
			ans = 0;
			
			for (int i = 0; i < N; i++) {
				st = new StringTokenizer(in.readLine()," ");
				for (int j = 0; j < M; j++) {
					map[i][j] = Integer.parseInt(st.nextToken());
				}
			} // end input
			
			answer.append('#').append(tc).append(' ').append(bfs()).append('\n');
		} // end test-case
		
		System.out.print(answer);
		in.close();
	} // end main

	private static int bfs() {
		queue = new LinkedList<Point>();
		queue.add(new Point(R,C));
		visited[R][C] = true;
		
		int size, time = 0;
		while(!queue.isEmpty()) {
			size = queue.size();
			time++;
			while(--size >= 0) {
				connect(queue.poll());
				ans++;
			}
			
			if(time == L)
				break;
		}
		queue.clear();
		return ans;
	}

	private static void connect(Point cur) {
		switch (map[cur.x][cur.y]) {
		case 1: // 상하좌우 터널과 연결
			for (int d = 0; d < delta.length; d++) {
				find(cur,d);
			}
			break;
		case 2: // 상하 터널과 연결
			find(cur,0);
			find(cur,2);
			break;
		case 3: // 좌우 터널과 연결
			find(cur,1);
			find(cur,3);
			break;
		case 4: // 상우 터널과 연결
			find(cur,0);
			find(cur,1);
			break;
		case 5: // 하우 터널과 연결
			find(cur,2);
			find(cur,1);
			break;
		case 6: // 하좌 터널과 연결
			find(cur,2);
			find(cur,3);
			break;
		case 7: // 상좌 터널과 연결
			find(cur,0);
			find(cur,3);
			break;
		}
	}
	
	
	private static void find(Point cur, int d) {
		visited[cur.x][cur.y] = true;
		int curX, curY;
		curX = cur.x + delta[d][0];
		curY = cur.y + delta[d][1];
		if (curX >= 0 && curX < N && curY >= 0 && curY < M && !visited[curX][curY] && map[curX][curY] > 0) {
			switch (d) {
			case 0: // 상
				if(map[curX][curY] == 1 || map[curX][curY] == 2 || map[curX][curY] == 5 || map[curX][curY] == 6) {
					queue.add(new Point(curX, curY));
					visited[curX][curY] = true;
				}
				break;
			case 1: // 우
				if(map[curX][curY] == 1 || map[curX][curY] == 3 || map[curX][curY] == 6 || map[curX][curY] == 7) {
					queue.add(new Point(curX, curY));
					visited[curX][curY] = true;
				}
				break;
			case 2: // 하
				if(map[curX][curY] == 1 || map[curX][curY] == 2 || map[curX][curY] == 4 || map[curX][curY] == 7) {
					queue.add(new Point(curX, curY));
					visited[curX][curY] = true;
				}
				break;
			case 3: // 좌
				if(map[curX][curY] == 1 || map[curX][curY] == 3 || map[curX][curY] == 4 || map[curX][curY] == 5) {
					queue.add(new Point(curX, curY));
					visited[curX][curY] = true;
				}
				break;
			}
		}
	}

	static class Point {
		int x;
		int y;
		
		public Point(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
}

BFS를 이용한 교수님 풀이

  • 메모리 : 26,556 KB
  • 실행시간 : 129 ms
  • 코드길이 : 2,635 B
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Solution_1953_탈주범검거_수업_BFS {

	static int N, M, R, C, L, ans;
	static Queue<Point> queue;
	static boolean[][] visited;
	static int[][] map;
	static int[][] delta = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } };
	static int[][] block_hole = { {}, // 0번 블럭 없음
			{ 1, 1, 1, 1 }, 
			{ 1, 0, 1, 0 }, 
			{ 0, 1, 0, 1 }, 
			{ 1, 1, 0, 0 }, 
			{ 0, 1, 1, 0 }, 
			{ 0, 0, 1, 1 },
			{ 1, 0, 0, 1 } };

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder answer = new StringBuilder();
		StringTokenizer st = null;
		int T = Integer.parseInt(in.readLine());
		for (int tc = 1; tc <= T; tc++) {
			st = new StringTokenizer(in.readLine(), " ");
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			R = Integer.parseInt(st.nextToken());
			C = Integer.parseInt(st.nextToken());
			L = Integer.parseInt(st.nextToken());
			map = new int[N][M];
			visited = new boolean[N][M];

			for (int i = 0; i < N; i++) {
				st = new StringTokenizer(in.readLine(), " ");
				for (int j = 0; j < M; j++) {
					map[i][j] = Integer.parseInt(st.nextToken());
				}
			} // end input

			
			answer.append('#').append(tc).append(' ').append(bfs()).append('\n');
		} // end test-case

		System.out.print(answer);
		in.close();
	} // end main

	private static int bfs() {
		queue = new LinkedList<Point>();
		queue.add(new Point(R, C));
		visited[R][C] = true;

		int size, time = 1;
		while (!queue.isEmpty() && time < L) {
			size = queue.size();
			while (--size >= 0) {
				Point now = queue.poll();
				int block = map[now.x][now.y];

				for (int d = 0; d < 4; d++) {
					// 현재 서 있는 블럭에 방향 d가 뚫려있는지
					if (block_hole[block][d] == 1) {
						int ni = now.x + delta[d][0];
						int nj = now.y + delta[d][1];

						if (ni >= 0 && ni < N && nj >= 0 && nj < M && map[ni][nj] > 0 && !visited[ni][nj]
								&& block_hole[map[ni][nj]][(d + 2) % 4] == 1) {
							visited[ni][nj] = true;
							queue.add(new Point(ni, nj));
						}
					}
				}
			} // end sec while
			time++;
		} // end first while
		ans = 0;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				if (visited[i][j])
					ans++;
			}
		}
		return ans;
	}

	static class Point {
		int x;
		int y;

		public Point(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
}

DFS를 이용한 교수님 풀이

  • 메모리 : 25,960 KB
  • 실행시간 : 141 ms
  • 코드길이 : 2,399 B
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Solution_1953_탈주범검거_수업_DFS {

	static int N, M, R, C, L, ans;
	static int[][] map;
	static int[][] delta = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } };
	static int[][] block_hole = { 
			{}, // 0번 블럭 없음
			{ 1, 1, 1, 1 }, 
			{ 1, 0, 1, 0 }, 
			{ 0, 1, 0, 1 }, 
			{ 1, 1, 0, 0 }, 
			{ 0, 1, 1, 0 }, 
			{ 0, 0, 1, 1 },
			{ 1, 0, 0, 1 } };

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder answer = new StringBuilder();
		StringTokenizer st = null;
		int T = Integer.parseInt(in.readLine());
		for (int tc = 1; tc <= T; tc++) {
			st = new StringTokenizer(in.readLine(), " ");
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			R = Integer.parseInt(st.nextToken());
			C = Integer.parseInt(st.nextToken());
			L = Integer.parseInt(st.nextToken());
			map = new int[N][M];

			for (int i = 0; i < N; i++) {
				st = new StringTokenizer(in.readLine(), " ");
				for (int j = 0; j < M; j++) {
					map[i][j] = Integer.parseInt(st.nextToken());
				}
			} // end input

			// dfs 사용시
			visited2 = new int[N][M];
			for (int[] row : visited2) {
				Arrays.fill(row, Integer.MAX_VALUE);
			}

			dfs(R, C, 1);
			ans = 0;
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < M; j++) {
					if (visited2[i][j] != Integer.MAX_VALUE)
						ans++;
				}
			}
			answer.append('#').append(tc).append(' ').append(ans).append('\n');
		} // end test-case

		System.out.print(answer);
		in.close();
	} // end main

	static int[][] visited2;

	private static void dfs(int i, int j, int time) {
		if (time == L + 1)
			return;

		visited2[i][j] = time;
		int block = map[i][j];

		for (int d = 0; d < 4; d++) {
			// 현재 서 있는 블럭에 방향 d가 뚫려있는지
			if (block_hole[block][d] == 1) {
				int ni = i + delta[d][0];
				int nj = j + delta[d][1];

				if (ni >= 0 && ni < N && nj >= 0 && nj < M && map[ni][nj] > 0 && (time < visited2[ni][nj])
						&& block_hole[map[ni][nj]][(d + 2) % 4] == 1) {
					dfs(ni, nj, time + 1);
				}
			}
		}
	}

	static class Point {
		int x;
		int y;

		public Point(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
}

Leave a comment