Coding Test
11. Baekjoon Gold5. '15686 치킨배달'
Daen12
2023. 4. 14. 00:28
이 문제는 백트래킹으로 남길 치킨집을 걸러주고,
브루트포스로 "모든 집"에 대해 "모든 남은 치킨 집"과의 거리를 계산해서 최솟값을 갱신해주었다.
처음 인풋받을 때 for루프 돌면서 치킨집과 집의 인덱스를 각각 ArrayList에 담아주었다.
코드는 아래와 같다.
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Q15686_치킨배달_gold5 {
// 브루트포스 & 백트래킹
// 치킨집을 n개 고르고
// 조합으로 치킨집 구한 후
// 각 집마다 구한 조합n개 중 최솟값 거리 구해서 누적 합 산출
static int N, M, chiCnt, ans;
static int[][] map;
static List<int[]> houses, chickens;
static boolean[] visited;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
N = in.nextInt();
M = in.nextInt(); // chickens
houses = new ArrayList<>();
chickens = new ArrayList<>();
map = new int[N][N];
chi = 0;
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
map[r][c] = in.nextInt();
if (map[r][c] == 1)
houses.add(new int[] { r, c });
else if (map[r][c] == 2) {
chi++;
chickens.add(new int[] { r, c });
}
}
}
ans = Integer.MAX_VALUE;
visited = new boolean[chi];
BackTracking(0, 0);
System.out.println(ans);
}
public static void BackTracking(int depth, int idx) {
if (depth == M) {
int[][] sel = new int[M][2];
int j = 0;
for (int i = 0; i < chiCnt; i++) {// 몇번째 치킨집이 선정되었는가
if (visited[i]) {
sel[j++] = chickens.get(i);
}
}
int sum = 0;
for (int i = 0; i < houses.size(); i++) {// home
int min = Integer.MAX_VALUE;
for (int k = 0; k < M; k++) {// chicken
min = Math.min(min, cal(houses.get(i)[0], houses.get(i)[1], sel[k][0], sel[k][1]));
}
sum += min;
}
ans = Math.min(ans, sum);
return;
}
for (int i = idx; i < chiCnt; i++) {
visited[i] = true;
BackTracking(depth + 1, i + 1);
visited[i] = false;
}
}
public static int cal(int hR, int hC, int cR, int cC) {
return Math.abs(hR - cR) + Math.abs(hC - cC);
}
}
백트래킹 함수에서 for루프 순환 시 선택된 치킨집을 따로 배열에 담지 않고
바깥 for루프 안에서 비교할 집을 선정 후 안쪽 for루프에서 선택된 치킨집인지 파악 -> 거리 파악의 순으로 작성해도 깔끔할 것 같다.