문제 : 백준 15686 치킨 배달 🍗
난이도 : 골드 5
1) 도시 정보 : 0 = 빈칸, 1 = 집, 2 = 치킨 집
1) 치킨 거리 : 집과 가장 가까운 치킨집 사이의 거리
즉, 치킨 거리는 집을 기준으로 정해지며, 각각의 집은 치킨 거리를 가지고 있다.
2) 도시의 치킨 거리 : 모든 집의 치킨 거리의 합
4) (r1, c1)과 (r2, c2) 사이의 거리 = |r1-r2| + |c1-c2|
- 집의 위치와 치킨의 위치를 각각 저장한다.
- 치킨집 중에서 M개의 치킨집을 선택한다. (조합)
- 각각 집마다 선택된 M개의 치킨집 중에서 가장 가까운 치킨 집까지의 거리(치킨 거리)를 구한다.
- 선택한 M개의 치킨 집 조합마다 모든 집의 치킨거리의 합(도시의 치킨 거리)를 구하고 그 중에서 가장 작은 도시의 치킨 거리를 구한다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int N =0, M=0; //도시의 크기, 치킨집의 최대 개수
int city=0; //도시의 정보 (0 : 빈칸, 1 : 집, 2 : 치킨집)
vector<pair<int,int>> home; //집의 좌표
vector<pair<int,int>> chicken; //치킨 집의 좌표
//1. 집의 위치와 치킨의 위치를 각각 저장한다.
cin>>N>>M;
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++){
cin>>city;
if(city == 1) home.push_back({i,j});
else if(city == 2) chicken.push_back({i,j});
}
}
//조합 구하기 - 보조 수열(전체 길이가 n개 , 1의 개수가 r개, 나머지가 0)
vector<int> visit;
for(int i=0; i<chicken.size()-M; i++){
visit.push_back(0);
}
for(int i=0; i<M; i++){
visit.push_back(1);
}
int min_homes_sum = 0x3f3f3f;
do{
int homes_sum = 0;
for(int i=0; i<home.size(); i++){
int min_home_sum = 0x3f3f3f;
for(int j=0; j<chicken.size(); j++){
if (visit[j] != 0) {
int sum = abs(chicken[j].first-home[i].first) + abs(chicken[j].second-home[i].second);
if(sum < min_home_sum) min_home_sum = sum;
//3. 각각 집마다 선택된 M개의 치킨집 중에서 가장 가까운 치킨 집까지의 거리(치킨 거리)를 구한다.
}
}
homes_sum = homes_sum + min_home_sum;
//4-1. 선택한 M개의 치킨 집 조합마다 모든 집의 치킨거리의 합(도시의 치킨 거리)를 구한다.
}
if(min_homes_sum > homes_sum) min_homes_sum = homes_sum;
// 4-2. 그 중에서 가장 작은 도시의 치킨 거리를 구한다.
}while(next_permutation(chicken.begin(), chicken.end()));
//2. 치킨집 중에서 M개의 치킨집을 선택한다. (조합)
cout<<min_homes_sum<<"\n";
}
#include <iostream>
#include <vector>
using namespace std;
vector<int> vec;
vector<int> map = {1,2,3};
bool check[3];
void DFS(int idx, int cnt){
cout<<"("<<idx<<","<<cnt<<")\n";
if(cnt == 2){
for(auto iter : vec){
cout<<iter<<" ";
}
cout<<"\n";
return;
}
for(int i=idx; i<map.size(); i++){
if(check[i]==true) continue;
check[i]=true;
vec.push_back(map[i]);
DFS(i,cnt+1);
check[i]=false;
vec.pop_back();
}
}
int main(){
DFS(0,0);
}
참고자료 : 순열과 조합 DFS로 구현 📒
https://charles098.tistory.com/9
https://paris-in-the-rain.tistory.com/35
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int N =0, M=0; //도시의 크기, 치킨집의 최대 개수
vector<pair<int,int>> vec; //선택된 M개의 치킨 집
vector<pair<int,int>> home; //집의 좌표
vector<pair<int,int>> chicken; //치킨 집 번호, 치킨 집의 좌표
int min_homes_sum = 0x3f3f3f;
bool check[13];
void DFS(int idx, int cnt){
if(cnt == M){ //M은 구하고 싶은 개수
int homes_sum = 0;
for(int i=0; i<home.size(); i++){
int min_home_sum = 0x3f3f3f;
for(int j=0; j<vec.size(); j++){
int sum = abs(vec[j].first-home[i].first) + abs(vec[j].second-home[i].second);
if(sum < min_home_sum) min_home_sum = sum;
//3. 각각 집마다 선택된 M개의 치킨집 중에서 가장 가까운 치킨 집까지의 거리(치킨 거리)를 구한다.
}
homes_sum = homes_sum + min_home_sum;
//4-1. 선택한 M개의 치킨 집 조합마다 모든 집의 치킨거리의 합(도시의 치킨 거리)를 구한다.
}
if(min_homes_sum > homes_sum) min_homes_sum = homes_sum;
// 4-2. 그 중에서 가장 작은 도시의 치킨 거리를 구한다.
return;
}
for(int i=idx; i<chicken.size(); i++){
if(check[i]==true) continue;
check[i]=true;
vec.push_back(chicken[i]);
DFS(i,cnt+1);
check[i]=false;
vec.pop_back();
}
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int city=0; //도시의 정보 (0 : 빈칸, 1 : 집, 2 : 치킨집)
//1. 집의 위치와 치킨의 위치를 각각 저장한다.
cin>>N>>M;
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++){
cin>>city;
if(city == 1) home.push_back({i,j});
else if(city == 2) chicken.push_back({i,j});
}
}
DFS(0,0); //idx = 0, cnt = 0
cout<<min_homes_sum<<"\n";
}