728x90
15686번: 치킨 배달
크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸
www.acmicpc.net
접근 방법
1. 폐업하지 않을 치킨집 M개를 선택한다.
2. 해당 폐업하지 않은 치킨집들과 집 사이의 거리들의 합 중 최소값을 구한다.
위 두 가지가 이번 문제의 핵심이다.
폐업하지 않을 치킨집을 고르는 방법 브루트포스밖에 없는 거 같다.
시간을 줄이기위해 백트래킹을 이용하기로 했다.
선택된 M개의 치킨집들과 집과의 거리의 최솟값을 구하기 위해
각 집마다 치킨집들과의 거리를 재어보고 이 중 가장 작은 것을 최종값에 더했다.
복잡한 문제는 아니므로 한번 풀어보자.
코드
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<cstring>
#define MAX 51
#define INF 9999999
using namespace std;
int n, m;
int res = INF;
int arr[MAX][MAX];
vector<pair<int, int>> chicken;
vector<pair<int, int>> home;
vector<int> selected;
int count() {
int total = 0;
for (int i = 0; i < home.size(); i++) {
int tmp = INF;
for (int j = 0; j < m; j++) {
tmp = min(
abs(home[i].first - chicken[selected[j]].first) +
abs(home[i].second - chicken[selected[j]].second)
, tmp
);
}
total += tmp;
}
//cout << "total: " << total << endl;
return total;
}
void select(int cnt, int idx) {
if (cnt == m) {
int tmp = count();
//cout << "tmp: " << tmp << endl;
res = min(res, tmp);
return;
}
for (int i = idx; i < chicken.size(); i++) {
selected.push_back(i);
//cout << "selected: " << i << endl;
select(cnt + 1, i + 1);
selected.pop_back();
}
}
int main() {
cin.tie(NULL); ios_base::sync_with_stdio(false);
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> arr[i][j];
if (arr[i][j] == 1)
home.push_back(make_pair(i, j));
else if(arr[i][j] == 2)
chicken.push_back(make_pair(i, j));
}
}
select(0, 0);
cout << res;
}
728x90
'📊알고리즘 > BOJ' 카테고리의 다른 글
BOJ 13335 - 트럭 (0) | 2024.03.31 |
---|---|
BOJ 14891 - 톱니바퀴 (0) | 2024.03.31 |
BOJ 14502 - 연구소 (0) | 2024.03.12 |
BOJ 2206 - 벽 부수고 이동하기 (0) | 2024.03.05 |
BOJ 1799 - 비숍 (🔄) (0) | 2024.02.29 |