문제 풀이/백준 / / 2024. 2. 4. 20:27

골드V 치킨 배달

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

 

15686번: 치킨 배달

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

www.acmicpc.net

기존 풀이에서는 백트래킹을 통해 각 치킨 집이 살아남는 모든 경우의 수를 2차원 배열에 반영하고

배열을 순회하면서 BFS를 사용하여 각 집에서 가장 가까운 치킨집과 그 거리를 구했습니다.

 

개선된 코드에서는 백트래킹으로 모든 경우의 수를 구하는 것은 같지만

N(집) 대 M(치킨집)으로 각 집과 치킨 집 사이의 거리를 모두 비교 후 최단 거리를 구했습니다.

기존 코드
개선 코드

// 기존 코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
    private static int result = (int)1e9;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] split = br.readLine().split(" ");

        int N = Integer.parseInt(split[0]);
        int M = Integer.parseInt(split[1]);
        int[][] city = new int[N][N];
        ArrayList<int[]> chickens = new ArrayList<>();

        for (int i = 0; i < N; i++) {
            String[] blocks = br.readLine().split(" ");
            for (int j = 0; j < N; j++) {
                int blockNum = Integer.parseInt(blocks[j]);
                if (blockNum == 2) {
                    chickens.add(new int[] {i, j});
                }
                city[i][j] = blockNum;
            }
        }

        dfs(city, chickens, M, chickens.size(), -1);
        System.out.println(result);
    }

    private static void dfs(int[][] city, ArrayList<int[]> chickens, int M, int chickenCnt, int idx) {
        if (M >= chickenCnt) {
            int totalChickenDistance = calculateTotalChickenDistance(city);
            if (totalChickenDistance < result) {
                result = totalChickenDistance;
            }
            return;
        }

        for (int i = 0; i < chickens.size(); i++) {
            if (i <= idx) {
                continue;
            }
            int[] chicken = chickens.get(i);
            city[chicken[0]][chicken[1]] = 0;
            dfs(city, chickens, M, chickenCnt - 1, i);
            city[chicken[0]][chicken[1]] = 2;
        }

    }

    private static int calculateTotalChickenDistance(int[][] city) {
        int N = city.length;
        int totalChickenDistance = 0;

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                int blockNum = city[i][j];
                if (blockNum == 1) {
                    totalChickenDistance += getNearestChickenDistance(city, i, j);
                }
            }
        }

        return totalChickenDistance;
    }

    private static int getNearestChickenDistance(int[][] city, int row, int col) {
        int[][] moves = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        boolean[][] visitMap = new boolean[city.length][city.length];

        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[] {row, col});

        while (!queue.isEmpty()) {
            int[] poll = queue.poll();
            int currentRow = poll[0];
            int currentCol = poll[1];
            if (city[currentRow][currentCol] == 2) {
                return getChickenDistance(row, col, currentRow, currentCol);
            }
            for (int[] move : moves) {
                int nextRow = currentRow + move[0];
                int nextCol = currentCol + move[1];
                if (!isInRange(city.length, nextRow, nextCol) || visitMap[nextRow][nextCol]) {
                    continue;
                }
                visitMap[nextRow][nextCol] = true;
                queue.add(new int[] {nextRow, nextCol});
            }
        }

        return 0;
    }

    private static boolean isInRange(int length, int row, int col) {
        return 0 <= row && row < length
                && 0 <= col && col < length;
    }

    private static int getChickenDistance(int homeRow, int homeCol, int chickenRow, int chickenCol) {
        return Math.abs(homeRow - chickenRow) + Math.abs(homeCol - chickenCol);
    }
}
// 개선 코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

import java.util.ArrayList;

public class Main {
    private int totalChickenDistance = (int)1e9;
    private final ArrayList<int[]> homes = new ArrayList<>();
    private final ArrayList<int[]> chickens = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        new Main().solution();
    }

    public void solution() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] split = br.readLine().split(" ");

        int N = Integer.parseInt(split[0]);
        int M = Integer.parseInt(split[1]);

        for (int row = 0; row < N; row++) {
            String[] blocks = br.readLine().split(" ");
            for (int col = 0; col < N; col++) {
                int blockNum = Integer.parseInt(blocks[col]);
                int[] coordinate = {row, col};
                if (blockNum == 1) {
                    homes.add(coordinate);
                } else if (blockNum == 2) {
                    chickens.add(coordinate);
                }
            }
        }

        dfs(M, chickens.size(), -1);
        System.out.println(totalChickenDistance);
    }

    private void dfs(int M, int surviveChickenCnt, int idx) {
        if (M >= surviveChickenCnt) {
            updateTotalChickenDistance(homes, chickens);
            return;
        }

        for (int i = 0; i < chickens.size(); i++) {
            if (i <= idx) {
                continue;
            }
            int[] chicken = chickens.get(i);
            chickens.set(i, null);
            dfs(M, surviveChickenCnt - 1, i);
            chickens.set(i, chicken);
        }

    }

    private void updateTotalChickenDistance(ArrayList<int[]> homes, ArrayList<int[]> chickens) {
        int sum = 0;

        for (int[] home : homes) {
            int minDistance = (int)1e9;
            for (int[] chicken : chickens) {
                if (chicken == null) {
                    continue;
                }
                minDistance = Math.min(minDistance, getChickenDistance(home[0], home[1], chicken[0], chicken[1]));
            }
            sum += minDistance;
        }
        totalChickenDistance = Math.min(totalChickenDistance, sum);
    }

    private int getChickenDistance(int homeRow, int homeCol, int chickenRow, int chickenCol) {
        return Math.abs(homeRow - chickenRow) + Math.abs(homeCol - chickenCol);
    }
}

'문제 풀이 > 백준' 카테고리의 다른 글

골드IV 공유기 설치  (0) 2024.08.15
골드III 불!  (1) 2024.08.11
플레티넘V 히스토그램에서 가장 큰 직사각형  (2) 2023.06.22
골드V 옥상 정원 꾸미기  (2) 2023.06.12
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유