Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
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
Archives
Today
Total
관리 메뉴

Life Engineering

[SWEA 1953] 탈주범 검거 (Java) 본문

Problem Solving

[SWEA 1953] 탈주범 검거 (Java)

흑개 2022. 4. 7. 18:08

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5PpLlKAQ4DFAUq&categoryId=AV5PpLlKAQ4DFAUq&categoryType=CODE&problemTitle=1953&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1&&&&&&&&& 

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

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 {
	static int[] dr= {-1,1,0,0};
	static int[] dc= {0,0,-1,1};
	static int[][] directions= {{0},{0,1,2,3},{0,1}, {2,3}, {0,3}, {1,3}, {1,2}, {0,2}};
	static int T, N, M;
	static int R, C, L;
	static int answer;
	static int[][] map;
	static boolean[][] visited;
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st=null;
		T=Integer.parseInt(br.readLine());
		for (int t=1; t<=T; t++) {
			answer=0;
			st=new StringTokenizer(br.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(br.readLine());
				for (int j = 0; j<M; j++) {
					map[i][j]=Integer.parseInt(st.nextToken());
				}
			}
			bfs(R, C);
			System.out.println("#"+t+" "+answer);
		}

	}
	private static void bfs(int startR, int startC) {
		Queue<int[]> q=new LinkedList<>();
		q.add(new int[] {startR, startC, map[startR][startC], 1});
		visited[startR][startC]=true;
		answer++;
		while (!q.isEmpty()) {
			int[] curr=q.poll();
			int r=curr[0];
			int c=curr[1];
			int type=curr[2];
			int time=curr[3];
			if (time==L) {
				break;
			}
			for (int d=0; d<directions[type].length; d++) {
				int dir=directions[type][d];
				int nr=r+dr[dir];
				int nc=c+dc[dir];
				if (nr<0 || nc<0 || nr>=N || nc>=M || map[nr][nc]==0) continue;
				if (!visited[nr][nc] && isPossible(dir, map[nr][nc])) {
					visited[nr][nc]=true;
					q.add(new int[] {nr, nc, map[nr][nc], time+1});
					answer++;
				}
			}
		}
		
	}
	private static boolean isPossible(int dir, int num) {
		int targetDir=-1;
		if (dir==0) targetDir=1;
		else if (dir==1) targetDir=0;
		else if (dir==2) targetDir=3;
		else targetDir=2;
		for (int i=0; i<directions[num].length; i++) {
			if (directions[num][i]==targetDir) return true;
		}
		return false;
	}

}

처음엔 하드코딩으로 풀었다..

isPossible 부분이 마음에 안들었다..

좌측으로 이동한 것에는 우측을 향하는 파이프가 있어야 하고,

상측으로 이동한 것에는 하측을 향하는 파이프가 있어야 한다.. 라는 조건을 isPossible에다 구현했는데,

이럴 필요 없이 각 type당 방향성을 0,1 로 표시하면 된다. 그 후 상/좌/하/우 로 dr, dx를 배열해서 (d+2)%4 로 체크가 가능하도록 한다.. 고친 코드는 아래에 있다.

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 {
	static int[] dr= {-1,0,1,0};
	static int[] dc= {0,-1,0,1};
	static int[][] directions= {{0,0,0,0},{1,1,1,1},{1,0,1,0}, {0,1,0,1}, {1,0,0,1},{0,0,1,1},{0,1,1,0},{1,1,0,0}};
	static int T, N, M;
	static int R, C, L;
	static int answer;
	static int[][] map;
	static boolean[][] visited;
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st=null;
		T=Integer.parseInt(br.readLine());
		for (int t=1; t<=T; t++) {
			answer=0;
			st=new StringTokenizer(br.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(br.readLine());
				for (int j = 0; j<M; j++) {
					map[i][j]=Integer.parseInt(st.nextToken());
				}
			}
			bfs(R, C);
			System.out.println("#"+t+" "+answer);
		}

	}
	private static void bfs(int startR, int startC) {
		Queue<int[]> q=new LinkedList<>();
		q.add(new int[] {startR, startC, map[startR][startC], 1});
		visited[startR][startC]=true;
		answer++;
		while (!q.isEmpty()) {
			int[] curr=q.poll();
			int r=curr[0];
			int c=curr[1];
			int type=curr[2];
			int time=curr[3];
			if (time==L) {
				break;
			}
			for (int d=0; d<directions[type].length; d++) {
				if (directions[type][d]==0) continue;
				int nr=r+dr[d];
				int nc=c+dc[d];
				if (nr<0 || nc<0 || nr>=N || nc>=M || map[nr][nc]==0) continue;
				if (!visited[nr][nc] && directions[map[nr][nc]][(d+2)%4]==1) {
					visited[nr][nc]=true;
					q.add(new int[] {nr, nc, map[nr][nc], time+1});
					answer++;
				}
			}
		}
		
	}
}