백준 15686 - 치킨 배달

1 minute read

문제링크

문제설명

  • N x N 크기의 도시가 주어진다. 도시는 1x1 크기의 칸으로 나누어져 있고, 도시의 각 칸은 빈 칸(0), 집(1), 치킨집(2) 중 하나이다.
  • 치킨 거리 는 집과 가장 가까운 치킨집 사이의 거리이다. 치킨 거리는 집을 기준으로 정해지며, 각각의 집은 치킨 거리를 가지고 있다.
  • 도시의 치킨 거리 는 모든 집의 치킨 거리의 합이다.
  • 거리는 맨하탄 거리 공삭을 따른다.
    • dist = abs(x1-x2) + abs(y1-y2)
  • 주어진 치킨집 중 M개만 뽑았을 때 도시의 치킨 거리의 최솟값을 구하라

문제접근

  • 배열 vector<pair<int, int>> chickenStore 을 선언하여 치킨집의 좌표를 담는다.
  • 치킨집 중 M개를 뽑는 로직은 재귀호출로 구현할 수 있다.
  • 각각의 집에서 가장 가까운 치킨집까지의 치킨 거리를 구하는 로직은 두가지 정도 아이디어가 있었다.
    • 각각의 집에 대하여 너비우선탐색으로 치킨집을 방문하게 되면 해당 치킨 거리를 반환한다. -> 시간초과
    • 집과 치킨집의 좌표를 명확하게 알고 있으므로 맨하탄 거리 공식으로 수식을 적용해서 구한다. -> 빠르고 간결함

구현

#include <iostream>
#include <vector>
#include <queue>	
#include <algorithm>
#include <cmath>
using namespace std;

int N, M;
int visited[13];
vector<pair<int, int>> chickenStore;
vector<pair<int, int>> house;
vector<pair<int, int>> cand;

int getDist(pair<int, int> hpos) {
	int dist =10000;
	for (auto chicken : cand) {
		dist = min(dist, abs(chicken.first - hpos.first) + abs(chicken.second - hpos.second));
	}
	return dist;
}

int getChickenDist(int v, int cnt) {
	if (cnt == M) {
		int dist = 0;
		for (auto ele : house) {
			dist += getDist(ele);
		}
		return dist;
	}

	int ret = 10000;
	for (int i = v; i < chickenStore.size(); i++) {
		if (visited[i]) continue;
		visited[i] = true;
		cand.push_back(chickenStore[i]);
		ret = min(ret, getChickenDist(i + 1, cnt + 1));
		cand.pop_back();
		visited[i] = false;
	}
	return ret;
}

int main()
{
	cin.tie(NULL);
	ios_base::sync_with_stdio(false);

	scanf("%d %d", &N, &M);
	int val = 0;
	for (int r = 0; r < N; r++) {
		for (int c = 0; c < N; c++) {
			scanf("%d", &val);
			if (val == 1) house.push_back(make_pair(r, c));
			else if (val == 2) chickenStore.push_back(make_pair(r, c));
		}
	}

	int ans = getChickenDist(0, 0);
	printf("%d", ans);
	return 0;

}

Leave a comment