문제 출처
1. 문제설명
- 크기가
NxN
인 도시가 있다.
- 각 칸의 거리는
|r1-r2| + |c1-c2|
2. 알고리즘 설계
BFS
로 각 집에서부터 치킨집의 거리를 구해야할 거 같지만 아니다.
BFS
문제와 달리 건물이 있든 말든 뛰어넘을 수 있다.
- 그래서 위와 같은 거리 계산 수식을 제공한 것이다.
3. 로직
- 집, 치킨집의 좌표를 저장해둔다.
- 저장된 치킨집 좌표 중 M개를 고르고,
- M개의 치킨집과 각 집의 거리를 전부 계산한다.
- 최소 거리와 현재 저장된 정답값을 비교해 갱신한다.
4. 전체 코드
#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
typedef struct { int y, x; } pos;
const int dy[] = { -1,1,0,0 };
const int dx[] = { 0,0,-1,1 };
const int SZ = 50, INF = 0x3f3f3f;
int n, m, ans, c[SZ][SZ];
bool selected[SZ];
vector<pos> house, chicken, pick;
int distance(pos a, pos b) { return abs(a.x - b.x) + abs(a.y - b.y); }
int find_min_distance() {
int ret = 0;
for (pos h : house) {
int tmp = INF;
for (pos chic : pick)
tmp = min(tmp, distance(h, chic));
ret += tmp;
}
return ret;
}
void dfs(int x, int cnt) {
if (m == cnt) {
int cmp = find_min_distance();
ans = min(cmp, ans);
}
for (int i = x; i < chicken.size(); i++) {
if (selected[i]) continue;
selected[i] = true;
pick.push_back(chicken[i]);
dfs(i, cnt + 1);
selected[i] = false;
pick.pop_back();
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> c[i][j];
if (c[i][j] == 1) house.push_back({ i,j });
if (c[i][j] == 2) chicken.push_back({ i,j });
}
}
ans = INF;
dfs(0, 0);
cout << ans;
return 0;
}
5. 소감
- BFS를 워낙 많이 풀었다보니,
- 1x1 크기의 맵이 주어지면, 자동으로 BFS로 경로를 탐색해야겠다는 생각이 든다.
- 하지만, 당연하게도 시간초과가 발생했다.