티스토리 뷰

[BJ] 15686. 치킨배달

www.acmicpc.net/problem/15686

 

15686번: 치킨 배달

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

www.acmicpc.net

 

✔ 문제 조건

  1. N * N, 빈칸 / 치킨집 / 집
  • r, c는 1부터 시작
  1. 치킨거리 : 집과 가장 가까운 치킨집과의 거리
  2. 도시의 치킨 거리 : 모든 집의 치킨 거리 합
  3. 치킨집 M개 빼고 모두 폐업 시킴
  4. 도시의 치킨 거리가 가장 작게 될 때의 치킨 거리 출력

✔ 접근 과정

  1. 치킨집, 집 list 생성
  2. dfs (combination/ 조합)으로 chicken.size()-M개의 치킨점을 폐업시킴
    close[L] = true -> 폐점
    close[L] = false -> 폐점 x
  3. 폐업되지 않은 치킨집과 집들간의 치킨 거리 구하며 최소값 찾기 - 브루트 포스

✔ 주의할 점

  1. M개를 골라서 폐점시키는게 아니라, M개 남기고 폐점하는 거다.
import java.io.*;
import java.util.*;
// 210419

public class Main_BJ_15686_치킨배달 {
	static int N, M, minDist; // 치킨집 M개 남기고 폐업
	static int[][] map; // 0: 빈칸, 1: 집, 2: 치킨집
	static boolean[] close; // 폐점시킬 치킨집
	static ArrayList<Pos> chicken, house;
	
	static class Pos {
		int r, c;

		public Pos(int r, int c) {
			this.r = r;
			this.c = c;
		}
	}
	
	public static void main(String[] args) throws Exception {
		//System.setIn(new FileInputStream("res/input_BJ_15686_치킨배달.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		
		N = stoi(st.nextToken());
		M = stoi(st.nextToken());
		minDist = Integer.MAX_VALUE;
		chicken = new ArrayList<Pos>();
		house = new ArrayList<Pos>();
		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] = stoi(st.nextToken());
				if(map[i][j]==1) house.add(new Pos(i, j));
				if(map[i][j]==2) chicken.add(new Pos(i, j));
			}
		}
		
		close = new boolean[chicken.size()];
		if(chicken.size()==M) getDist();
		else {
			comb(0, 0);
		}
 
		System.out.println(minDist);
		br.close();
	}
	
	// 1. 폐업시킬 치킨집 고르기
	static void comb(int cnt, int L) { 
		// M개를 폐업시키는게 아니라 M개만 살려놓고 나머지를 폐업시킨다.
		if(cnt==chicken.size()-M) {
			getDist();
			return;
		}
		
		if(L==chicken.size()) return;
		
		close[L] = true;
		comb(cnt+1, L+1);
		
		close[L] = false;
		comb(cnt, L+1);
	}
	
	// 2. 폐업되지 않은 치킨집과 집들간의 치킨거리 구하기
	static void getDist() {
		int total = 0;
		
		for(int i=0; i<house.size(); i++) {
			Pos h = house.get(i);
			
			int min = Integer.MAX_VALUE;
			for(int j=0; j<chicken.size(); j++) {
				if(close[j]) continue;
				Pos c = chicken.get(j);
				min = Math.min(min, cal(h.r, h.c, c.r, c.c));
			}
			total += min;
			if(total > minDist) return;
		} 
		minDist = Math.min(minDist, total);
	}
	
	static int cal(int r1, int c1, int r2, int c2) {
		return Math.abs(r1-r2) + Math.abs(c1-c2);
	}
 
	static int stoi(String str) {
		return Integer.parseInt(str);
	}

}

'코딩테스트 > 백준' 카테고리의 다른 글

[BJ] 2636. 치즈  (0) 2021.04.22
[BJ] 19238. 스타트 택시  (0) 2021.04.21
[BJ] 16236. 아기상어  (0) 2021.04.20
[BJ] 14503. 로봇 청소기  (0) 2021.04.20
[BJ] 19237. 어른 상어  (0) 2021.04.14
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함