본문 바로가기

BOJ

백준 4991 / 로봇 청소기






총 n개의 쓰레기를 치우는 최소거리는


치우는 순서에 따라 다르다.


그렇기에 1,2......, 최대 10번째 쓰레기를 치우는 순서를 모두 정한 후


최소값을 구하면 된다.


총 10!(>300만)개의 경우의수가 생기니 next_permutation 안에서 bfs를 매번 돌리면 시간초과가 뜬다. 





해결법은


로봇청소기와 쓰레기 n개 사이의 거리를 모두 구해놓는 것이다.


쓰레기가 10개라고 가정하면


로봇청소기와 쓰레기 사이의 거리 : 10개


쓰레기와 쓰레기 사이의 거리 : 10C2개


총 55개의 거리를 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
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include<stdio.h>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<memory.h>
#include<string>
 
using namespace std;
 
int dx[] = { 1,-1,0,0 };
int dy[] = { 0,0,-1,1};
 
char map[21][21];
bool check[21][21];
int dist[21][21];
 
int dirtdist[12][12];
 
int h, w;
 
int bfs(int a, int b, int fx, int fy) {
 
    memset(check, falsesizeof(check));
    memset(dist, 0sizeof(dist));
 
    queue<pair<intint>>q;
 
    q.push({ a,b });
    check[a][b] = true;
 
    while (!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
 
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx >= 0 && nx < h && ny >= 0 && ny < w) {
                if (check[nx][ny] == false) {
                    if (map[nx][ny] == '.' || map[nx][ny] == '*' || map[nx][ny]=='o') {
                        check[nx][ny] = true;
                        dist[nx][ny] = dist[x][y] + 1;
                        q.push({ nx,ny });
                    }
                }
            }
        }
    }
 
    return dist[fx][fy];
    
}
 
int main() {
 
    //freopen("Text.txt", "r", stdin);
 
    while (1) {
 
        memset(dirtdist, 0sizeof(dirtdist));
 
        cin >> w >> h;
 
        if (w == 0 && h == 0) {
            break;
        }
        
        int dirt = 0;
        bool can = true;
        int ssx = 0;
        int ssy = 0;
 
        vector<pair<intint>>dirtxy;
 
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                cin >> map[i][j];
                if (map[i][j] == '*') {
                    dirt++;
                    dirtxy.push_back({ i,j });
                }
                if (map[i][j] == 'o') {
                    ssx = i;
                    ssy = j;
                }
            }
        }
        for (int i = 0; i < dirt; i++) {
 
            int sx = dirtxy[i].first;
            int sy = dirtxy[i].second;
 
            int tmp = bfs(ssx, ssy, sx, sy);
 
            if (tmp == 0) {
                can = false;
                break;
            }
            else {
                dirtdist[11][i] = tmp;
            }
 
            for (int j = i+1; j < dirt; j++) {
            
                if (i != j) {
                    int sx = dirtxy[i].first;
                    int sy = dirtxy[i].second;
                    int fx = dirtxy[j].first;
                    int fy = dirtxy[j].second;
 
                    int tmp = bfs(sx, sy, fx, fy);
            
                    dirtdist[i][j] = tmp;
                    dirtdist[j][i] = tmp;
                }
            }
        }
 
        vector<int>order;
        
        for (int i = 0; i < dirt; i++) {
            order.push_back(i);
        }
 
        int min = -1;
 
        do {
 
            int sx = ssx;
            int sy = ssy;
 
            int ans = 0;
 
            if (can == false || dirt == 0)break;
 
            ans += dirtdist[11][order[0]];
 
            for (int i = 0; i < dirt - 1; i++) {
                ans += dirtdist[order[i]][order[i + 1]];
            }
 
            if (min > ans || min == -1){
                min = ans;
            }
 
        } while (next_permutation(order.begin(), order.end()));
 
        if (dirt == 0) {
            cout << 0 << endl;
        }
        else {
            if (can == false || min == 0) {
                cout << -1 << endl;
            }
            else {
                cout << min << endl;
            }
        }
    }
}
cs



'BOJ' 카테고리의 다른 글

백준 15558 / 점프 게임  (0) 2019.02.07
백준 6087 / 레이저 통신  (0) 2019.02.07
백준 9328 / 열쇠  (0) 2019.02.06
백준 12851 / 숨바꼭질 2  (0) 2019.02.01
백준 1525 / 퍼즐  (0) 2019.01.31