반응형
문제 : https://www.acmicpc.net/problem/15686
서론
재귀를 이용한 완전탐색문제.
아이디어
2차원 배열을 만들지는 않고, 지도를 입력받을때 1이면 집 벡터에 좌표를 넣어주고 2면 치킨 벡터에 좌표를 넣어준다.
도시에 있는 치킨집 중 최대 M개를 골라서 가장 작은 도시의 치킨거리를 구해야하는데, 최대M개를 고르라고 해서 M개를 고르는 경우의 수, M-1을 고르는 경우의 수, M-2를 고르는 경우의 수 ....를 고려할 필요는 없이 M개를 고르는 경우의 수만 고려하면 된다. 치킨집이 M-1에 비해 M개면 수익이 감소할지는 모르나 우리는 치킨거리만 고려하면 되고, 치킨거리는 치킨집이 많을수록 당연히 작다.
그래서 도시에 있는 총 치킨집 중 M개를 골라야 하는데, 고를 수 있는 모든 경우의 수를 얻기 위해 재귀를 이용한 완전탐색을 진행한다.
만약 도시의 치킨집의 개수가 4, M이 2면
1번 | 2번 | 3번 | 4번 |
T | T | F | F |
T | F | T | F |
T | F | F | T |
F | T | T | F |
F | T | F | T |
F | F | T | T |
(T는 치킨집을 선택, F는 치킨집을 선택하지 않음)
총 6개의 경우의 수가 나오고 코드는
recursive(index, selectCount, select){
if(select == true) 치킨집[index] = true
if(selectCount == M) 도시의 치킨거리 계산()
recursive(index+1, selectCount+1, true)
recursive(index+1, selectCount, false)
}
index는 치킨집의 번호, selectCount는 치킨집을 선택한 개수, select는 이번 치킨집을 선택했을 때이며
위와 같은 방법으로 도시에 있는 치킨집 중 M개를 선택했다.
그리고 M개를 선택한 경우의 수 마다 도시의 치킨거리를 계산하고, 이 도시의 치킨거리들 중 최소값이 치킨집 중 어떤 M개를 선택했을때 도시의 치킨거리가 최소값이 나올 때이다.
도시의 치킨거리는
도시의 치킨거리 = 0
for(i=0;집 전체;i++){
집 치킨거리 = 매우 큰 값
for(j=0;치킨집 전체;j++) {
if(치킨집[i] == 선택받았음) 집 치킨거리 = min(집 치킨거리, 집[i]와 치킨집[j] 거리 계산 값)
}
도시의 치킨거리 += 집 치킨거리
}
출력값 = min(출력값, 도시의 치킨거리) // selectCount가 M일때마다 갱신될 수 있음
구현
// c++
#include <algorithm>
#include <vector>
#include <iostream>
typedef struct st{
int y;
int x;
bool select;
}st;
std::vector<st>house;
std::vector<st>chicken;
int n, m;
int result = 0x7f7f7f7f;
void input() {
std::cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
int tmp;
std::cin >> tmp;
if (tmp == 1) house.push_back({ i, j, false });
else if (tmp == 2)chicken.push_back({ i, j, false });
}
}
}
void rec(int idx, int selCnt, bool select) {
if (idx != -1) chicken[idx].select = select;
if (selCnt == m) {
int dist = 0;
for (int i = 0, hSize = house.size(); i < hSize; i++) {
int tmpDist = 0x7f7f7f7f;
for (int j = 0, cSize = chicken.size(); j < cSize; j++) {
if (chicken[j].select == true) {
tmpDist = std::min(tmpDist, abs(house[i].y - chicken[j].y) + abs(house[i].x - chicken[j].x));
}
}
dist += tmpDist;
}
result = std::min(dist, result);
return;
}
else if (idx == chicken.size() - 1) {
return;
}
rec(idx + 1, selCnt + 1, true);
rec(idx + 1, selCnt, false);
return;
}
int main() {
input();
rec(-1, 0, false);
std::cout << result;
}
최근댓글