🧫 문제 분석
✔️ 출처
📖 문제

// 치킨 거리 = 집과 가장 까가운 치킨집 사이의 거리
// 집 기준, 집은 치킨거리를 가짐
// 도시의 치킨 거리 = 모든 집의 치킨 거리의 합
// 임의의 두 칸 (r1, c1)과 (r2, c2) 사이의 거리는 |r1-r2| + |c1-c2|
// 0 빈칸 , 1 집 , 2 치킨 집
// 집의 개수 <= 2N , 적어도 1개는 존재
// M <= 치킨집의 개수 <= 13
치킨 집 중 M개를 골라야하기에 백트래킹이 필요하다.
중요한 것은 전체 치킨 집 수 중 M개를 뽑는 방법이다.
처음에 그냥 i = 0 으로 모든 치킨집을 순회하면서 조합을 만들어갔기에 시간초과로 실패했다.
중요한 것은 m개의 치킨집을 효율적으로 뽑아서 치킨거리를 계산하는 것이다.
치킨집을 뽑을때 이전에 뽑았던 가게는 이미 뽑혔기에 굳이 또 방문할 필요없다.
따라서 +1을 해주어서 그다음 가게부터 순회하도록한다.
🔅 문제 풀이
import java.io.*;
import java.util.*;
public class Main {
static class Location {
int r, c;
public Location(int r, int c) {
this.r = r;
this.c = c;
}
}
static int m; // 치킨 집 개수
static int chickenStreet = Integer.MAX_VALUE;
static boolean[] visited;
static ArrayList<Location> house = new ArrayList<>();
static ArrayList<Location> chicken = new ArrayList<>();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken()); // 크기 n x n
m = Integer.parseInt(st.nextToken());
for (int i = 1; i <= n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 1; j <= n; j++) {
String info = st.nextToken();
if (info.equals("1")) {
house.add(new Location(i, j));
} else if (info.equals("2")) {
chicken.add(new Location(i, j));
}
}
}
visited = new boolean[chicken.size()];
recursion(0, 0);
bw.write(chickenStreet + "\n");
bw.flush();
bw.close();
}
// 치킨 가게 중 m 개를 뽑는다.
private static void recursion(int depth, int start) {
// m개가 뽑히면 도시의 치킨거리 최솟값을 구한다.
if (depth == m) {
int tmp = clacMin();
chickenStreet = Math.min(tmp, chickenStreet);
return;
}
for (int i = start; i < chicken.size(); i++) {
if (!visited[i]) {
visited[i] = true;
recursion(depth + 1,i + 1); // 조합을 효율적으로 나누는 방법
visited[i] = false;
}
}
}
// 각 집마다 m개로 뽑힌 치킨가게와의 최소 거리 구하기
private static int clacMin() {
int tmp = 0;
for (int i = 0; i < house.size(); i++) {
int min = Integer.MAX_VALUE;
Location home = house.get(i);
for (int j = 0; j < chicken.size(); j++) {
if (visited[j]) {
Location chick = chicken.get(j);
int street = Math.abs(home.r - chick.r) + Math.abs(home.c - chick.c);
if (street < min)
min = street;
}
}
tmp += min;
}
return tmp;
}
}
❗ 오답노트 / 필요한 지식
- start 부터 시작하면서 i+1을 넘겨주는 방법을 몰라서 계속 시간초과가 떴다. 사실 엄청 당연한 건데 많이 반성하게 된다. 시간복잡도를 생각하고 효율적으로 짜보자..
'baekjoon > Graph_Search' 카테고리의 다른 글
백준 14500번 : 테트로미노 자바 (0) | 2024.08.19 |
---|---|
백준 2644번 : 촌수계산 자바 (0) | 2024.08.17 |
백준 13549번 : 숨바꼭질 3 자바 (0) | 2024.08.08 |
백준 1759번 : 암호 만들기 자바 (0) | 2024.07.16 |
백준 16234번 : 인구 이동 자바 (0) | 2024.06.29 |