[BOJ 15686] 치킨 배달
업데이트:
문제
- BOJ 15686
- 문제의 저작권은 Baekjoon Online Judge에 있습니다.
접근방식
한달전에 한번 풀었던 문제라 쉽게 풀린 문제였다.
전체 치킨집 중 M개를 뽑은 각 경우의 수에서 집으로 부터 치킨거리를 구하고 이를 합한 도시의 치킨거리를 순서대로 구하면 된다.
M개를 뽑는데는 조합을 사용하였다. 조합은 브루트포스에서 많이 사용되므로 반드시 코드를 이해+암기해두자!!
생성된 경우의 수는 전체 치킨 리스트의 인덱스를 나타내므로 각 집으로 부터 치킨거리를 구할때는 반드시 chickens.get(numbers[j])
에 접근해야 한다. 다 구해놓고 아무 생각없이 chickens.get(j)
해서 헤맸음… 집중.. 또 집중할 것!
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class Boj15686 {
static ArrayList<Point> homes; //집 좌표 담을 배열
static ArrayList<Point> chickens; //치킨 좌표 담을 배열
static int[] selected; //뽑은 경우의 수
static int[] numbers; //전체 인덱스
static int N, M;
static StringTokenizer st;
static int Ans = Integer.MAX_VALUE; //최소가 되는 도시의 치킨거리
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
homes = new ArrayList<>();
chickens = new ArrayList<>();
for(int i=0; i<N; i++) {
st = new StringTokenizer(br.readLine());
for(int j=0; j<N; j++) {
int input = Integer.parseInt(st.nextToken());
if(input == 1) homes.add(new Point(i, j));
if(input == 2) chickens.add(new Point(i, j));
}
}
Ans = Integer.MAX_VALUE;
selected = new int[M];
numbers = new int[chickens.size()];
for(int i=0; i<chickens.size(); i++) numbers[i] = i;
comb(0, 0); //전체 치킨집 중 M개 뽑기(조합)
System.out.println(Ans);
}
private static void comb(int cnt, int cur) {
if(cnt == M) { //경우의 수를 구했으면
int cityLength = 0;
for(int i=0; i<homes.size(); i++) { //모든 집을 돌면서
Point home = homes.get(i);
int chickenLength = Integer.MAX_VALUE; //치킨거리
for(int j=0; j<selected.length; j++) { //각 집에서 치킨거리(최소거리) 구하기
Point chicken = chickens.get(selected[j]);
int dist = getDistance(home.x, home.y, chicken.x, chicken.y);
chickenLength = Math.min(chickenLength, dist);
}
cityLength += chickenLength; // 모든 집의 치킨거리 누적합 = 도시의 치킨거리
}
Ans = Math.min(Ans, cityLength);
return;
}
for(int i=cur; i<chickens.size(); i++) {
selected[cnt] = numbers[i];
comb(cnt+1, i+1);
}
}
private static int getDistance(int x1, int y1, int x2, int y2) {
return Math.abs(x1-x2)+Math.abs(y1-y2);
}
static class Point{
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}