본문 바로가기
Algorithm/문제 풀이 (Problem Solving)

[C++,구현,BFS,DFS] 백준 15686번 치킨 배달 문제풀이

by matters_ 2019. 5. 25.

문제링크

백준 15686번 치킨 배달

 

15686번: 치킨 배달

크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸, 왼쪽에서부터 c번째 칸을 의미한다. r과 c는 1부터 시작한다. 이 도시에 사는 사람들은 치킨을 매우 좋아한다. 따라서, 사람들은 "치킨 거리"라는 말을 주로 사용한다. 치킨 거리는 집과 가장 가까운 치킨집 사이의 거리이다. 즉, 치킨 거리는

www.acmicpc.net

 

DFS,BFS를 모두 쓴 조금은 힘든? 문제이다. 최대 M개의 치킨집을 고르는 건 DFS, 치킨집을 골라 최소거리를 구하는 건 BFS로 구현하였다. 밑에 코드에 나와있듯이 치킨집을 선정할 때 예외처리를 잘 못해줘서 애를 먹었던 문제이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <queue>
using namespace std;
int n,m,ans=1987654321
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int map[50][50],dis[50][50],zero[50][50],check[50][50];
vector <pair<int,int> >chickk,chick;
vector <pair<int,int> >house;
 
void copy_map(int (*a)[50],int (*b)[50]){//복사함수
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
        a[i][j]=b[i][j];
}
 
void cnt_dis(){
    copy_map(check,zero);//bfs를 위한 방문check 초기화
    queue <pair<int,int> >cchick;
    for(int i=0;i<chickk.size();i++){//벡터에서 큐로 치킨집옮기기
        cchick.push(make_pair(chickk[i].first,chickk[i].second));
        check[chickk[i].first][chickk[i].second]=1;
    }
 
    while(!cchick.empty()){//bfs로 dis배열에 최소거리 계산
        int a=cchick.front().first,b=cchick.front().second;
        
        cchick.pop();
        for(int i=0;i<4;i++){
            int x=a+dx[i],y=b+dy[i];
            if(    x>=0&&x<n&&y>=0&&y<n&&!check[x][y]){
                check[x][y]=1;
                dis[x][y]=dis[a][b]+1;
                cchick.push(make_pair(x,y));
            }
        }
    }
}
 
void dfs(int depth,int x,int y){
    if(depth==m){ //최대 m번 했으면
        copy_map(dis,zero);
        cnt_dis();//거리계산
        int tmp=0;
        for(int i=0;i<house.size();i++){//map에 있는 모든 집거리의 합
            tmp+=dis[house[i].first][house[i].second];
        }
        if(ans>tmp)ans=tmp;//최소값 찾기
        return;
    }
    
    int j=y,flag=0;
    int t_map[50][50];
    for(int i=x;i<n;i++){
        if(flag)j=0;
        for(;j<n;j++){
            flag=1;
            if(map[i][j]==2){
                chickk.push_back(make_pair(i,j));//치킨집 후보들 vector에 넣기
                if(j+1>=n) dfs(depth+1,i+1,0);///j+1될때 예외처리 꼭해주자!!!!
                else dfs(depth+1,i,j+1);//다음 치킨집으로
                chickk.pop_back(); //벡터에서 제외
            }
        }
    }
    
}
main(){
    ios::sync_with_stdio(0);
    cout.tie(NULL);
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            cin>>map[i][j];
            if(map[i][j]==1)house.push_back(make_pair(i,j));//집좌표 담기
            else if(map[i][j]==2)chick.push_back(make_pair(i,j));//치킨집 좌표 담기
        }
    for(int i=0;i<chick.size();i++)    dfs(0,chick[i].first,chick[i].second);//치킨집 골라서 dfs
    cout<<ans;
}
cs

입력을 받을 떄 집좌표와 치킨집좌표를 벡터와 저장한 후 

치킨집이 있는 곳을 기준으로 DFS탐색을 하는 dfs함수로 들어간다. 

dfs가 재귀적으로 호출되어 m번 반복됬으면 cnt_dis함수로 거리를 계산한다. 

여기서 거리는 BFS으로 계산하며 치킨집을 기준으로 거리를 계산 한 후 

집의 좌표값을 넣어 합을 구하고 최소값을 도출하는 방식이다. 

 

 

 

댓글