알고리즘/백준 BAEK JOON

14503.로봇청소기

IMyoungho 2020. 6. 1. 00:51

이번에 풀어볼 문제는 백준 14503 로봇청소기이다. 시뮬레이션 분류의 문제이며 문제 이해만 잘하면 풀 수 있는 문제이다.

 

14503번: 로봇 청소기

로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어

www.acmicpc.net

하지만 제대로 이해못하거나 설계를 잘못하면 미궁속에 빠져서 푼거 또 풀고 푼거 또 풀게된다...

나 역시 1주일전에 풀다가 틀린 부분을 못찾아서 1주일 후에 다시 푸는데 성공했다(그사이에 늘긴 늘었다보다..)

내가 실수했던 부분은 후진에 대한 내용이다. 4방향모두 갈곳이 없을 때 청소한 곳을 지나갈 수 있는 방법은 후진뿐인데

잘못이해해서 후진말고도 갈 수 있는거 아닌가 라고 착각했다.

 

역시나 설계가 제일 중요하다!

=> 이제는 구현은 허접하게라도 할 수있는 레벨이므로 설계를 잘해야한다.

 

 


 

< Code 설명 >

 

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

#pragma
 warning(disable:4996)
#include <iostream>
#include <deque>
#define MAX 51
 
using namespace std;
 
// 북 동 남 서
int dx[4= { -1010 };
int dy[4= { 010-1 };
 
int n, m;
int r, c, d;
int cnt = 0// 탐색횟수
int ans = 1// 정답저장변수
int map[MAX][MAX];   // 맵이 저장되는 배열
int check[MAX][MAX]; // 청소한 곳 체크할 배열
 
int before_x, before_y; // 3방향 뒤져서 막혀있으면 되돌아갈 좌표
int tmp_x, tmp_y; // 임시 좌표가 저장될 변수
 
deque<pair<intint>> t;// 방향이 저장된 deque
 
void showme(){ // 보여줘 배열상태를!!
    cout << "\n";
    for (int i = 0; i < n; i++){
        for (int j = 0; j < m; j++){
            printf("%2d ", map[i][j]);
        }
        cout << "\n";
    }
    cout << "\n";
    cout << "\n";
    for (int i = 0; i < n; i++){
        for (int j = 0; j < m; j++){
            printf("%2d ", check[i][j]);
        }
        cout << "\n";
    }
    cout << "\n";
}
 
void turn_set(){ // 청소기 시작방향 선정될 함수
    for (int i = 0; i < 4; i++// 기준 방향 순차적 저장
        t.push_back(make_pair(dx[i], dy[i]));
    
    for (int i = 0; i < d; i++){ // 시작방향 셋팅
        t.push_back(t.front());
        t.pop_front();
    }
}
 
void turn(){ // 방향 전환 함수
    t.push_front(t.back());
    t.pop_back();
}
 
 
 
void search(int x, int y){
    turn(); // 좌측을 방향 전환
    int ax = x + t.front().first; //좌측 x좌표 
    int ay = y + t.front().second;//좌측 y좌표
    if (ax <= 0 || ay <= 0 || ax >= n || ay >= m){ //범위확인
        cnt += 1// 청소할 수 없는 경우로 탐색 숫자 +1
        return;
    }
 
    // 청소가 가능한 경우 (벽이 아니면서 청소안된구역)
    if (map[ax][ay] != 1 && check[ax][ay] == 0){ 
        ans += 1// 청소횟수 증가
        check[ax][ay] = ans; // 청소 횟수 저장
        tmp_x = ax; // 청소한 x좌표 저장
        tmp_y = ay; // 청소한 y좌표 저장
        cnt = 0;    // 청소했으니 탐색 숫자 초기화
    }
    else // 청소가 불가능하면 탐색 +1 그 방향 회전 후 탐색은 다시돌아가서하게됨
        cnt += 1;
}
 
 
int main(){
    freopen("14503.txt""r", stdin);
    cin >> n >> m;
    cin >> r >> c >> d;
    for (int i = 0; i < n; i++){
        for (int j = 0; j < m; j++){
            cin >> map[i][j];
        }
    }
    tmp_x = r; // 시작 x좌표 저장
    tmp_y = c; // 시작 y좌표 저장
    check[r][c] = 1//시작 좌표 청소 
    turn_set();  // 방향 설정
    while (true){
        search(r, c);// 탐색 
        //showme();
        r = tmp_x; // 탐색 후 청소된 x좌표 저장
        c = tmp_y; // 탐색 후 청소된 y좌표 저장
        if (cnt == 4){ // 4방향 탐색 후 갈곳이 없다면 후진!
        // 후진은 가려는 방향의 반대이므로 반대로 계산하는 로직
            if (t.front().first < 0 && t.front().second == 0){ 
                r += -1 * t.front().first;
            }
            else if (t.front().first > 0 && t.front().second == 0){
                r -= t.front().first;
            }
            else if (t.front().first == 0 && t.front().second < 0){
                c += -1 * t.front().second;
            }
            else if (t.front().first == 0 && t.front().second > 0){
                c -= t.front().second;
            }
            if (map[r][c]==1// 4방향 탐색 후 후진시에 벽이나오면
                break// 시동끈다
            cnt = 0// 후진했으니 탐색 숫자 초기화
            tmp_x = r; // 후진한 x좌표 저장
            tmp_y = c; // 후진한 y좌표 저장
        }
    }
 
    cout << ans << "\n";
    return 0;
}
cs

 

반응형