반응형
어떻게 풀까?
해당 문제는 전형적인 조합 문제입니다.
생각해봐야할 과제는 다음과 같습니다.
1. 맵에서 치킨집의 개수를 추출한 후에 비트 조합을 이용해서 m개의 치킨집만을 고른다.
2. 사람들이 사는 모든 집에서 현재 선택된 m개의 치킨 집 중에서 최소의 치킨집을 구한 후 더한다. (도시의 치킨 거리를 구한다.)
3. 최소의 도시의 치킨 거리 값을 출력한다.
만약, 비트 조합을 만드실줄 모른다면 여기를 참조하세요!
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 | typedef struct Cod{ int r,c; } cod; int cNum, pNum; cod company[13]; cod people[100]; int getAllDist() { int visit = (1 << m) - 1; int max = (1 << cNum); int minDist = 999999; while (visit < max) { int temp = visit | (visit - 1); int dist = 0; for (int i = 0; i < pNum; i++) { //i번쨰 사람의 치킨 거리를 구한다. dist += getDistance(i, visit); } //도시의 minDist = min(minDist, dist); visit = (temp + 1) | (((~temp & -~temp) - 1) >> (getZeros(visit) + 1)); } return minDist; } | cs |
이 부분이 바로 비트 조합을 이용해서 도시의 치킨 거리를 구하는 부분입니다.
그럼 이제, i번째 사람의 치킨 거리는 어떻게 구하면 될까요!?
현재 선택된 m개의 치킨 집들이 모두 비트로 표시되어 있습니다.
따라서, 이 정보들로 부터 i 번째 사람에서 현재 선택된 치킨 집들 까지의 모든 거리를 구할 수 있고,
이 중에서 최솟값이 바로 치킨 거리 입니다.
만약, 비트 연산을 잘 모르신다면 여기를 참조하세요!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | typedef struct Cod{ int r,c; } cod; int cNum, pNum; cod company[13]; cod people[100]; int getDistance(int num, int select) { int index = 0; int dist = 99999; while (select) { if (select & 1) { int tempDistance; tempDistance = abs(people[num].r - company[index].r) + abs(people[num].c - company[index].c); dist = min(tempDistance, dist); } select >>= 1; index++; } return dist; } | 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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | #include<iostream> #include<cstring> using namespace std; struct ChickenInfo { int map[50][50]; int n; int m; typedef struct Cod{ int r,c; } cod; int cNum, pNum; cod company[13]; cod people[100]; int abs(int i) { return i > 0 ? i : -i; } int min(int i1, int i2) { return i1 < i2 ? i1 : i2; } int getDistance(int num, int select) { int index = 0; int dist = 99999; while (select) { if (select & 1) { int tempDistance; tempDistance = abs(people[num].r - company[index].r) + abs(people[num].c - company[index].c); dist = min(tempDistance, dist); } select >>= 1; index++; } return dist; } int getZeros(int n) { int res = 0; while ((n & 1) == 0) { res++; n >>= 1; } return res; } int getAllDist() { int visit = (1 << m) - 1; int max = (1 << cNum); int minDist = 999999; while (visit < max) { int temp = visit | (visit - 1); int dist = 0; for (int i = 0; i < pNum; i++) { dist += getDistance(i, visit); } minDist = min(minDist, dist); visit = (temp + 1) | (((~temp & -~temp) - 1) >> (getZeros(visit) + 1)); } return minDist; } void init() { memset(map, 0, sizeof(map)); pNum = cNum = 0; 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) { people[pNum].r = i; people[pNum].c = j; pNum++; } else if (map[i][j] == 2) { company[cNum].r = i; company[cNum].c = j; cNum++; } } } } }ChickInfo; int main() { ChickInfo.init(); int res = ChickInfo.getAllDist(); cout << res << '\n'; return 0; } | cs |
시간 복잡도
우선, 사람들의 수를 i라고 하겠습니다.
치킨 거리를 구하기 위해서는 i개의 집들이 m개의 치킨수를 모두 확인해야 합니다.
그리고, 조합은.. 최악의 경우도을 넘지 않기 때문에
시간 복잡도는 입니다.
반응형
'공부 > 알고리즘 문제풀이' 카테고리의 다른 글
[삼성 기출 문제] 백준 16236 아기 상어 (0) | 2019.03.12 |
---|---|
[삼성 기출 문제] 백준 16234 인구 이동 (2) | 2019.03.12 |
[삼성 기출 문제] 백준15685 드래곤 커브 (0) | 2019.03.11 |
[삼성 기출 문제] 백준15684 사다리 조작 (0) | 2019.03.11 |
[삼성 기출 문제] 백준 15683 감시 (0) | 2019.03.11 |