본문 바로가기

Dot Algo∙ DS/PS

[프로그래머스] 2021 카카오 인턴 #2 거리두기 확인하기 (Java)

    #2 거리두기 확인하기

    난이도 : LEVEL 2

    유형 : 그래프 / BFS

     

    코딩테스트 연습 - 거리두기 확인하기

    [["POOOP", "OXXOX", "OPXPX", "OOXOX", "POXXP"], ["POOPX", "OXPXP", "PXXXO", "OXXXO", "OOOPP"], ["PXOPX", "OXOXP", "OXPOX", "OXXOP", "PXPOX"], ["OOOXX", "XOOOX", "OOOXX", "OXOOX", "OOOOO"], ["PXPXP", "XPXPX", "PXPXP", "XPXPX", "PXPXP"]] [1, 0, 1, 1, 1]

    programmers.co.kr

    문제

    개발자를 희망하는 죠르디가 카카오에 면접을 보러 왔습니다.

    코로나 바이러스 감염 예방을 위해 응시자들은 거리를 둬서 대기를 해야하는데 개발 직군 면접인 만큼
    아래와 같은 규칙으로 대기실에 거리를 두고 앉도록 안내하고 있습니다.

    • 대기실은 5개이며, 각 대기실은 5x5 크기입니다.
    • 거리두기를 위하여 응시자들 끼리는 맨해튼 거리1가 2 이하로 앉지 말아 주세요.
    • 단 응시자가 앉아있는 자리 사이가 파티션으로 막혀 있을 경우에는 허용합니다.

    예를 들어,

     

     

    5개의 대기실을 본 죠르디는 각 대기실에서 응시자들이 거리두기를 잘 기키고 있는지 알고 싶어졌습니다. 자리에 앉아있는 응시자들의 정보와 대기실 구조를 대기실별로 담은 2차원 문자열 배열 places가 매개변수로 주어집니다. 각 대기실별로 거리두기를 지키고 있으면 1을, 한 명이라도 지키지 않고 있으면 0을 배열에 담아 return 하도록 solution 함수를 완성해 주세요.

     

    제한사항

    • places의 행 길이(대기실 개수) = 5
      • places의 각 행은 하나의 대기실 구조를 나타냅니다.
    • places의 열 길이(대기실 세로 길이) = 5
    • places의 원소는 P,O,X로 이루어진 문자열입니다.
      • places 원소의 길이(대기실 가로 길이) = 5
      • P는 응시자가 앉아있는 자리를 의미합니다.
      • O는 빈 테이블을 의미합니다.
      • X는 파티션을 의미합니다.
    • 입력으로 주어지는 5개 대기실의 크기는 모두 5x5 입니다.
    • return 값 형식
      • 1차원 정수 배열에 5개의 원소를 담아서 return 합니다.
      • places에 담겨 있는 5개 대기실의 순서대로, 거리두기 준수 여부를 차례대로 배열에 담습니다.
      • 각 대기실 별로 모든 응시자가 거리두기를 지키고 있으면 1을, 한 명이라도 지키지 않고 있으면 0을 담습니다.

     

    문제 풀이  

    그래프 탐색 문제로 5x5 대기실이라는 맵에서 한 사람(P)과 다른 사람의 거리가 *맨해튼 거리(2)이하를 갖고있으면 해당 대기실은 방역수칙을 지키고 있지 않은 대개실로 간주하여 0을 출력해주고 모두가 거리두기를 잘하고 있으면 1을 해준다.

    *맨해튼 거리 : 두 테이블 T1, T2가 행렬 (r1, c1), (r2, c2)에 각각 위치하고 있다면, T1, T2 사이의 맨해튼 거리는 |r1 - r2| + |c1 - c2| 이다.

     

    해당 문제에서 '반'에 해당하는 것은 맨해튼 거리가 2이하로 앉아있는 사람들이다. 그러므로 각 그래프를 BFS로 탐색하면서 두 사람간의 최단거리가 2이하인 대기실을 찾으면 0을 반환하는 방식으로 로직을 짜주면 된다.

     

    구상

    1. String타입 데이터 배열을 int타입으로 변환 map = new int[5][5]
    2. 주어진 5개의 대기실 각각 탐색하여 사람(P) 위치 저장 List<Node> seat_list
      1. 각 대기실마다 사람들 맨해튼 거리 준수하는지 BFS 탐색 bfs(p.x, p.y)
      2. 이번에 탐색한 사람은 다음 탐색 대상에서 제외 map[x][y]=1;

     

    풀이 코드 

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Queue;
    
    class Solution {
       static class Node{
          int x;
          int y;
          int move;
    		
          public Node(int x, int y, int move){
             this.x = x;
             this.y = y;
             this.move = move;
          }
       }
       static int[][] map;
       static int[] answer;
       static int[] dx = {-1,1,0,0};
       static int[] dy = {0,0,-1,1};
       public int[] solution(String[][] places) {
            answer = new int[places.length];
            for(int i=0; i<places.length; i++) {
            	answer[i] =1;
            }
            
            // String타입 데이터 int타입으로 변환
            // P 사람 : 32, O 빈 테이블: 31, X 파티션 : 40   
            for(int t = 0; t<5; t++) {
            	map = new int[5][5];
            	List<Node> seat_list = new ArrayList<>();
            	
    	        for(int i=0; i<places[t].length; i++) {
    	        	String line = places[t][i];
    	        	for(int j=0; j<line.length(); j++) {
    	        		map[i][j] = line.charAt(j)-'0';
    				// 사람(P) 위치 저장
    	        		if(map[i][j] == 32) {
    	        			seat_list.add(new Node(i,j,0));
    	        		}
    	        	}
    	        }
    	        // t대기실 사람들 맨해튼 거리 준수하는지 BFS 탐색
    	        for(Node p : seat_list) {
    	        	int res = bfs(p.x, p.y);
    	        	if(res == 0) {
    	        		answer[t] = 0; // t대기실은 거리두기를 지키고있지 않음 0 
    	        		break;
    	        	}
    	        }
            }
            return answer;
        }
    	static int bfs(int x, int y) {
    		Queue<Node> q = new LinkedList<>();
    		boolean[][] check = new boolean[5][5];
    		
    		check[x][y] = true;
    		map[x][y] =1; // 이번에 탐색한 사람은 다음 탐색 대상에서는 예외시켜줌
    		q.add(new Node(x,y,0));
    		while(!q.isEmpty()) {
    			Node pos = q.poll();
    			int move = pos.move;
    			
    			if(map[pos.x][pos.y] == 32) {
    				if(move<=2) return 0; // 맨해튼 거리가 2이하이면 0 반환 
    			}
    			
    			for(int i=0; i<4; i++) {
    				int nx = pos.x+dx[i];
    				int ny = pos.y+dy[i];
    				
    				if(nx <0 || ny<0 || nx>4 || ny>4) continue;
    				if(check[nx][ny]) continue;
                    
    				// // 파티션은 맨해튼 거리가 적용되지 않으므로 탐색 x 				
    				if(map[nx][ny] != 40) { 
    					check[nx][ny]= true;
    					q.add(new Node(nx,ny, move+1));
    				}
    			}
    		}
    		return 1;
    	}
    }