본문 바로가기
Algorithm/백준풀이

[알고리즘 문제풀이] 백준 15686 치킨 배달 (JAVA코드)

by 계범 2022. 4. 6.

목차

    https://www.acmicpc.net/problem/15686

     

    15686번: 치킨 배달

    크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸

    www.acmicpc.net

    /**
     * 1. 50*50 맵 크기. 최대 13개의 치킨집 고를 수 있음
     * 
     * 2. m개의 치킨집 선택.
     * 2-1) 50*50 에서 m개를 고를려면 시간복잡도 문제가 됨..
     * 2-2) 맵에서 치킨집리스트를 별도로 빼고, 그 안에서 선택!(최대 13개 있다고 함.)
     * 2-3) 13개중에서 m개 선택 시간복잡도. 13Cm
     * 
     * 3. 선택한 치킨집에서 집리스트를 돌면서 거리 계산.
     *    전체 치킨집(13) * 집리스트(최대2n)
     * 3-1) 치킨집마다 각 집으로의 거리 중 최소값을 저장
     * 
     * 4. m개의 치킨집에서 다 해본 결과의 전체 치킨 거리를 정답에 저장
     * 
     * 5. m개를 고를 수 있는 모든 경우의 수 수행한 후 최소값 출력
     * 
     * 13Cm * m*2n
     */
    
    import java.util.*;
    import java.io.*;
    
    
    public class Main {
    
        public static int n,m,answer = Integer.MAX_VALUE;
        public static int[][] map;
        public static ArrayList<int[]> chicken,home;
        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());
    
            map = new int[n][n];
            chicken = new ArrayList<>();
            home = new ArrayList<>();
    
            for(int i = 0; i < n; i++){
                st = new StringTokenizer(br.readLine());
                for(int j = 0; j < n; j++){
                    int num = Integer.parseInt(st.nextToken());
    
                    if(num == 1){
                        home.add(new int[] {i,j});
                    }else if(num == 2){
                        chicken.add(new int[] {i,j});
                    }
                    map[i][j] = num;
                }
            }
    
            dfs(0,0,-1);
    
            System.out.println(answer);
        }
    
        // 치킨집 고르는 함수
        public static void dfs(int stage,int check,int pidx){
            // 다 고른 경우
            if(stage == m){
                calc(check);
                return;
            }
    
            // 고르기(비트마스킹을 통해 방문여부 체크)
            for(int i = pidx+1; i < chicken.size(); i++){
                if((check & (1<<i)) == 0){
                    dfs(stage+1,check + (1<<i),i);
                }
            }
        }
    
        // 고른 치킨집 돌면서 거리 계산 함수
        public static void calc(int check){
            int[] dis = new int[home.size()]; // 각 집까지의 거리 저장
            Arrays.fill(dis,Integer.MAX_VALUE);
    
            for(int i = 0; i < chicken.size(); i++){
                if((check & (1<<i)) != 0){ // 선택된 치킨집일때 체크
                    for(int j = 0; j <home.size(); j++){
                        int[] chicken_pos = chicken.get(i);
                        int[] home_pos = home.get(j);
    
                        int curDis = Math.abs(chicken_pos[0]-home_pos[0])
                                    + Math.abs(chicken_pos[1] - home_pos[1]);
                        
                        dis[j] = Math.min(dis[j],curDis);
                    }
                }
            }
    
            int temp = 0;
            for (int i : dis) {
                temp += i;
            }
    
            answer = Math.min(answer, temp);
        }
    }

    댓글