PS/백준

[ 백준 ] 15686번 : 치킨 배달 - ( C++/C/CPP )

발효홍삼 2022. 3. 15. 23:06
728x90
  •  문제

https://www.acmicpc.net/problem/15686

 

15686번: 치킨 배달

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

www.acmicpc.net


  • 풀이법 ( 알고리즘 )

처음엔 단순히 모든 치킨집과 집들의 거리를 계산해 그중 m개의 최소 수들을 구해 더했으나 tc부터 막혔다.

생각해보니 폐업을 시킨 후 도시의 치킨 거리를 구해야 하기 때문에 위의 방법은 틀린 방법이었다.

문제를 읽고 깊게 생각해보지 않으니 이런 황당한 실수를 하는 거 같다.

dfs를 돌며 모든 치킨집에 대해 계산했다면 폐업시키지 않은 치킨집과 각 집들의 거리 중 최소 거리를 구하고 더했다.

이후 최소 도시의 치킨 거리를 구해 출력해주었다.

1시간 동안 삽질했다.. 이런 실수는 줄이도록 노력해야겠다.


  • 풀이 - C++
#include <iostream>
#include <vector>
#include <algorithm>
#define MAX 987654321

using namespace std;


int m, n, ans = MAX; // n : 도시의 넓이 n * n , m : 폐업하지 않는 치킨집의 개수 , ans : 답 저장
bool closing[14]; // closing[x] : x번째 치킨집을 폐업시켰는지 저장
vector <pair<int, int>> chicken, house;

void dfs(int idx, int cnt)
{
	if (idx > chicken.size()) return;

	if (cnt == m) //m개의 치킨집이 정해지면
	{
		int tmp = 0;
		for (int i = 0; i < house.size(); i++)
		{
			int d = MAX;

			for (int j = 0; j < chicken.size(); j++)
			{
				if (closing[j]) //j번째 치킨집을 사용한다면
				{
					d = min(d, abs(house[i].first - chicken[j].first) + abs(house[i].second - chicken[j].second));
				}
			}
			tmp += d;
		}

		ans = min(ans, tmp);
		return;
	}

	closing[idx] = true; //현재 치킨집을 폐업하지 않는 경우
	dfs(idx + 1, cnt + 1);
	closing[idx] = false; //현재 치킨집을 폐업하는 경우
	dfs(idx + 1, cnt);
}

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	//input
	cin >> n >> m;

	int t;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cin >> t;
			if (t == 1)  house.push_back({ i,j }); //1은 집
			else if (t == 2) chicken.push_back({ i,j }); //2는 치킨집
		}
	}

	//solve
	dfs(0, 0);

	cout << ans;

	return 0;
}
728x90