알고리즘/BaekJoon

백준 15686 : 치킨 배달

꾸준하게 :) 2020. 2. 17. 21:08

문제 링크입니다 https://www.acmicpc.net/problem/15686

 

15686번: 치킨 배달

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

www.acmicpc.net

1. 도시의 정보 중 빈칸을 제외한 치킨집과 집의 좌표를 vector를 사용해 입력받는다.

   (어차피 이 문제의 경우 거리를 구해야 하는 문제이기 때문에 빈칸의 좌표가 필요 없었습니다!)

 

2. 모든 치킨집 중에서 M개를 고른다.

3. 모든 집들에 대해서 고른 M개의 치킨집과의 거리를 구하고 그 중 최솟값이 그 집의 '치킨 거리'이다.

4. 모든 집들에 대해 3번에서 구한 '치킨 거리들의 합'들 중에서 최솟값이 정답이다.

 

전체 치킨집 중에서 M개를 골랐을 때의 모든 경우 중에서 치킨 거리가 가장 짧아지는 경우에 도시의 치킨 거리의 최솟값을 출력하는 문제였습니다. 이 문제에서는 도시의 정보 전체를 이차원 배열 형태로 입력받을 필요가 없었습니다.

 

 

[소스코드 + 주석]

 

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
80
81
82
83
84
85
86
87
88
89
90
91
92
// [백준] 삼성 SW 역량 테스트 기출 문제 : 치킨 배달(15686)
 
#include<algorithm>
#include<vector>
#include<cstdio>
using namespace std;
const int MAX = 13 + 10;    // 1 <= M <= 13
 
// 좌표를 저장하기 위한 구조체
struct p {
    int y, x;
};
vector <p> home;            // 집의 좌표를 입력받을 vector
vector <p> chicken_jib;     // 치킨집의 좌표를 입력받을 vector
 
bool check[MAX];    // 치킨집을 고를 때 이미 고른 치킨집을 또 고르지 않기 위한 check 배열
int n, m, what, ret, result[MAX];
 
// 좌표를 인자로 받아서 p type으로 바꿔주는 함수
p make_p(int y, int x) {
    p temp;
 
    temp.y = y, temp.x = x;
    return temp;
}
 
// 입력을 받는 함수
void input_info(void) {
    scanf("%d%d"&n, &m);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d"&what);
            if (what == 2) chicken_jib.push_back(make_p(i, j));
            else if (what == 1) home.push_back(make_p(i, j));
        }
    }
    ret = 987987987;
}
 
// 치킨집 M개를 고른 후 모든 집들에 대해서 M개의 치킨집과의 거리 중 최솟값을 구하고
// 모든 집들의 치킨 거리를 누적하여 더한 값(도시의 치킨거리)을 반환하는 함수
int getDist(void) {
    int min_dist_sum = 0;    // 도시의 치킨 거리를 구하기 위한 변수
    
    for (int i = 0; i < home.size(); i++) {
        
        int min_dist = 987987987;    // 하나의 집에 대한 치킨 거리를 구하기 위한 변수
        
        for (int j = 0; j < m; j++) {
 
            int hy = home[i].y, hx = home[i].x;    // 집의 좌표
 
            int cy = chicken_jib[result[j]].y;     // 치킨집의 좌표
            int cx = chicken_jib[result[j]].x;    
 
            int temp = abs(hy - cy) + abs(hx - cx);
            min_dist = min(min_dist, temp);
        }
        min_dist_sum += min_dist;
    }
    return min_dist_sum;
}
 
// M개의 치킨집을 골라서 도시의 치킨거리를 최솟값으로 update 해주는 함수
void getResult(int count, int start) {
    if (count == m) {
        int temp = getDist();    // M개의 치킨집을 골랐을 때, 도시의 치킨거리를 받아
        ret = min(ret, temp);    // 최종 결과값에는 최솟값을 찾아서 넣는다
    }
    else {
        // M개의 치킨집을 고르는 과정
        for (int i = start; i < chicken_jib.size(); i++) {
            if (!check[i]) {
                check[i] = true;
                result[count] = i;
                getResult(count + 1, i + 1);
                check[i] = false;
            }
        }
    }
}
 
int solve(void) {
    input_info();
    getResult(00);
    return ret;
}
 
int main(void) {
    printf("%d", solve());
    return 0;
}
cs

 

 

[소스코드]

 

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
#include<algorithm>
#include<vector>
#include<cstdio>
using namespace std;
const int MAX = 13 + 10;
 
struct p {
    int y, x;
};
vector <p> home;
vector <p> chicken_jib;
 
bool check[MAX];
int n, m, what, ret, result[MAX];
 
p make_p(int y, int x) {
    p temp;
 
    temp.y = y, temp.x = x;
    return temp;
}
 
void input_info(void) {
    scanf("%d%d"&n, &m);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d"&what);
            if (what == 2) chicken_jib.push_back(make_p(i, j));
            else if (what == 1) home.push_back(make_p(i, j));
        }
    }
    ret = 987987987;
}
 
int getDist(void) {
    int min_dist_sum = 0;
    for (int i = 0; i < home.size(); i++) {
        int min_dist = 987987987;
        for (int j = 0; j < m; j++) {
            int hy = home[i].y, hx = home[i].x;
            int cy = chicken_jib[result[j]].y;
            int cx = chicken_jib[result[j]].x;
 
            int temp = abs(hy - cy) + abs(hx - cx);
            min_dist = min(min_dist, temp);
        }
        min_dist_sum += min_dist;
    }
    return min_dist_sum;
}
 
void getResult(int count, int start) {
    if (count == m) {
        int temp = getDist();
        ret = min(ret, temp);
    }
    else {
        for (int i = start; i < chicken_jib.size(); i++) {
            if (!check[i]) {
                check[i] = true;
                result[count] = i;
                getResult(count + 1, i + 1);
                check[i] = false;
            }
        }
    }
}
 
int solve(void) {
    input_info();
    getResult(00);
    return ret;
}
 
int main(void) {
    printf("%d", solve());
    return 0;
}
cs

 

'알고리즘 > BaekJoon' 카테고리의 다른 글

백준 2503 : 숫자 야구  (0) 2020.02.18
백준 6603 : 로또  (0) 2020.02.18
백준 1065 : 한수  (0) 2020.02.17
백준 2231 : 분해합  (0) 2020.02.17
백준 16236 : 아기 상어  (0) 2020.02.16