Algorithm/Problem

치킨 배달(BJ_15686)

당진개발자 2024. 8. 29. 20:56

1. 문제 링크

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

 

 


 

2. 나의 코드

메모리: 18120 kb
시간: 184 ms
코드 길이: 1977 B
시간 복잡도 : O(2^C * HC)
설명
- 조합 알고리즘 사용
- 완전 탐색
import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

public class BJ_15686 {

    static List<Point> houses;
    static List<Point> chickens;
    static int[][] map;
    static Point[] input;
    static int N, M, result;

    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());
        houses = new ArrayList<Point>();
        chickens = new ArrayList<Point>();
        map = new int[N][N];
        input = new Point[M];
        result = Integer.MAX_VALUE;

        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] == 1) houses.add(new Point(i, j));
                else if (map[i][j] == 2) chickens.add(new Point(i, j));
            }
        }

        comb(0, 0);
        System.out.println(result);
    }

    public static void comb(int cnt, int start) {

        if (cnt == M) {
            int sumDist = 0;
            for (Point house : houses) {
                int minDist = Integer.MAX_VALUE;
                for (Point chicken : input) {
                    int dist = Math.abs(house.x - chicken.x) + Math.abs(house.y - chicken.y);
                    minDist = Math.min(minDist, dist);
                }
                sumDist += minDist;
            }
            result = Math.min(sumDist, result);
            return;
        }

        for (int i = start; i < chickens.size(); i++) {
            input[cnt] = chickens.get(i);
            comb(cnt + 1, i + 1);
        }
    }
}

 


 

3. 정답 코드

import java.util.*;
 
public class Main {
 
    static int n, m;
    static int[][] board;
    static int min = Integer.MAX_VALUE;
    static ArrayList<Node> chickenList = new ArrayList<>(); //치킨집 위치를 저장하는 리스트 
    static ArrayList<Node> houseList = new ArrayList<>(); // 집의 위치를 저장하는 리스트
    static boolean[] chickenVisited; // 뽑은 치킨집 체크
    
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
 
        n = scan.nextInt();
        m = scan.nextInt();
        
        board = new int[n][n];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                board[i][j] = scan.nextInt();
                if(board[i][j] == 1) houseList.add(new Node(i, j));
                else if(board[i][j] == 2) chickenList.add(new Node(i, j));
            }
        }
        
        chickenVisited = new boolean[chickenList.size()];
        backtracking(0, 0); //m개의 치킨집을 뽑는다.
        System.out.println(min);
    }
    
    public static void backtracking(int count, int idx) {
        if(count == m) { //치킨 거리의 최솟값을 구한다.
            int total = 0; // 도시의 치킨거리
            for(int i = 0; i < houseList.size(); i++) {
                int sum = Integer.MAX_VALUE;
                for(int j = 0; j < chickenList.size(); j++) {
                    if(chickenVisited[j] == true) { //i번째 집에서부터 j번짜 치킨집 까지의 거리 중 최소값을 구한다.
                        int dist = Math.abs(houseList.get(i).x - chickenList.get(j).x) 
                                + Math.abs(houseList.get(i).y - chickenList.get(j).y);
                        sum = Math.min(sum, dist);
                    }
                }
                total += sum;
            }
            min = Math.min(total, min);
            return;
        }
        
        for(int i = idx; i < chickenList.size(); i++) {
            if(chickenVisited[i] == false) {
                chickenVisited[i] = true;
                backtracking(count + 1, i + 1);
                chickenVisited[i] = false;
            }
        }
    }
    
    public static class Node {
        int x;
        int y;
        
        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
}

 


 

4. 배운 점

- 완전 탐색으로 풀 수 있는 경우는 완탐으로 풀자.

- 순열과 조합은 제대로 공부하자