SSONG Cloud
[백준] 15686 치킨 배달 본문
반응형
문제 출처: www.acmicpc.net/problem/15686
15686번: 치킨 배달
크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸
www.acmicpc.net
: 현재 존재하는 치킨집들 중에서 최대로 M개만 남길 수 있고 다른 지점들은 없애게 된다.
: 치킨집과 집의 거리를 치킨거리라고 하는데 이때, 최소 치킨 거리를 구해야 한다.
: 먼저 남길 치킨집들을 부분집합으로 구한다.
: 남기려고 하는 치킨집의 수가 M보다 크면 이 경우는 조건에 부합하지 않으므로 그냥 넘긴다.
: M이하인 경우에는 치킨거리들의 합을 구해야 한다.
: 치킨 거리의 합은 집들을 순회하면서 가장 가까운 치킨거리를 구하고 이를 더하면 된다.
: 각각의 치킨거리의 합이 현재까지 구했던 치킨거리 총합보다 작으면 갱신하는 과정을 반복한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class 치킨배달 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StringBuilder sb = new StringBuilder();
static StringTokenizer st;
static int[][] map;
static int N, M;
static boolean[][] v;
static boolean[] selected;
static ArrayList<Point> home = new ArrayList<>();
static ArrayList<Point> chi = new ArrayList<>();
static class Point{
int r, c;
public Point(int r, int c) {
super();
this.r = r;
this.c = c;
}
}
public static void main(String[] args) throws IOException {
// N:행렬의 크기 , M:살아남을 수 있는 치킨집의 최대 개수
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][N];
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) home.add(new Point(i, j));
// 행렬을 입력받으면서 치킨집의 좌표 배열로 저장
else if(map[i][j] == 2) chi.add(new Point(i,j));
}
}
selected = new boolean[chi.size()];
powerset(0);
System.out.println(ans);
}
// 치킨집을 부분집합으로 뽑으면서
private static void powerset(int idx) {
if(idx == chi.size()) {
int cnt = 0;
for(int i = 0, size = chi.size(); i < size; i++) {
if(selected[i]) cnt++;
}
// 뽑힌 치킨집의 개수가 M개를 넘으면 그냥 return 시키고
if(cnt > M || cnt== 0) return;
// 넘지 않았을 때 뽑힌 치킨집들로 부터의 거리를 구해서 갱신
int val = calc(selected);
ans = ans > val ? val : ans;
return;
}
selected[idx] = true;
powerset(idx+1);
selected[idx] = false;
powerset(idx+1);
}
static int ans = Integer.MAX_VALUE;
private static int calc(boolean[] sel) {
int sum = 0;
for(int i = 0, size = home.size(); i < size; i++ ) {
int min = Integer.MAX_VALUE;
// 집마다 선택된 치킨집으로부터의 최소 거리를 구함
for(int j = 0, size2 = chi.size(); j < size2; j++) {
if(selected[j]) {
int diff = Math.abs(home.get(i).r - chi.get(j).r)
+ Math.abs(home.get(i).c - chi.get(j).c);
min = min > diff ? diff : min;
}
}
sum += min;
}
return sum;
}
}
반응형
'Algorithm > 백준' 카테고리의 다른 글
[백준] 1194 달이 차오른다, 가자. (0) | 2021.04.14 |
---|---|
[백준] 1759 암호 만들기 (0) | 2021.04.14 |
[백준] 1965 상자넣기 (0) | 2021.04.14 |
[백준] 17471 게리맨더링 (0) | 2021.04.14 |
[백준] 1292 쉽게 푸는 문제 (0) | 2021.04.10 |
Comments