코딩공작소
[백준]로봇청소기(2,3번째 풂) 본문
https://www.acmicpc.net/problem/14503
14503번: 로봇 청소기
로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북중 하나이다. 지도의 각 칸은 (r, c)로 나타낼 수 있고, r은 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로 부터 떨어진 칸의 개수이다. 로봇 청소기는 다음
www.acmicpc.net
시뮬레이션으로 구현했다.
과정은 반복하기때문에, 재귀함수를 사용하는것은 마찬가지였고, 주어진 과정대로 그냥 코딩했다.
실수를 한 점은, 왼쪽을 체크하고 움직이는 과정이 따로따로 진행되는데 한번에 했기 때문에, 체크하는 과정에서
이미 움직여지고 후진이 제대로 되지않았다. 그래서 따로따로 만들어서 구현해주었다.(요구한 대로 만들어야한다)
그리고 4방향을 모두 체크하는 방법으로는 cnt변수를 사용해서 카운트하고 return을 해주었다.
과정 과정마다 cout을 해주면서 코딩을 하는 방법이 좋은거 같다. 다 완성하고 cout을 해보는것 보다 만들면서 그때그때
제대로 동작하는지 출력하는것이 좋을것 같다.
**계속 빠져나오지 못했었는데, 이유가 위에서 재귀함수를 돌렸는데, 재귀가 끝나고 그 아래것들이 실행되서 무한으로
돌았다. else에 return만 해주었기때문에, if문에서 재귀를 실행한것이 아래로 쭈욱 실행되었다.
1
2
3
4
5
|
if(A) {}
else {return;} //else인 경우에 return함.
cout <<"Hello" ; //if인경우에 if문을 전부 실행하고 Line 3으로 옴.
**재귀함수를 쓸때, 맨 아래 Line에서 쓰서 종료가 되게 하거나, 도중에 쓰여있다면 잘 종료해야한다.**
|
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
|
#include <iostream>
#include <vector>
using namespace std;
int R, C,answer = 1;
int r, c, d , left_d; //북(0),동(1),남(2),서(3)
int dr[] = {-1,0,1,0};
int dc[] = {0,1,0,-1};
int map[51][51];
bool InRange(int r, int c) { //범위검사. 시작지점에 따라 다름(*주의*)
if (r < 0 || c < 0 || r >= R || c >= C) return false;
else return true;
}
bool CheckLeft(int &next_r,int &next_c) { //체크만 하는 함수
if (d == 0) left_d = 3;
else if (d == 1) left_d = 0;
else if (d == 2) left_d = 1;
else if (d == 3) left_d = 2;
//int next_r, next_c;
next_r = r + dr[left_d]; next_c = c + dc[left_d];
if (InRange(next_r,next_c) && map[next_r][next_c] == 0) { //왼쪽방향의 곳에 청소를 할 수 있다면
return true;
}
else { //청소 할수 없다면
return false;
}
}
void TurnLeft() { //방향전환
if (d == 0) d = 3;
else if (d == 1) d = 0;
else if (d == 2) d = 1;
else if (d == 3) d = 2;
}
void clean(int cnt) {
if (cnt == 4) { //4방향모두 No청소
//후진할 방향.
int next_r, next_c , n_d;
if (d == 0) n_d = 2;
else if (d == 1) n_d = 3;
else if (d == 2) n_d = 0;
else if (d == 3) n_d = 1;
next_r = r + dr[n_d]; next_c = c + dc[n_d]; //후진 방향
if (InRange(next_r,next_c) && map[next_r][next_c] != 1) {//후진가능
r = next_r; c = next_c; //후진
clean(0); //다시 청소
}
return; //후진불가 and 후진한 후, 종료 //재귀함수에서 가장 중요한 탈출조건
}
int next_r, next_c; //다음으로 향할 곳.
//있다면 (a), 없다면 (b)
if (CheckLeft(next_r, next_c)) {TurnLeft(); r = next_r; c = next_c; map[next_r][next_c] = 2; answer++; clean(0); }
else { TurnLeft(); clean(cnt+1); }
}
int main()
{
cin >> R >> C;
cin >> r >> c >> d;
for (int i = 0; i < R; i++) for (int j = 0; j < C; j++) cin >> map[i][j];
map[r][c] = 2; //현재위치 청소
clean(0);
cout << answer << endl;
return 0;
}
|
cs |
<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
30
31
32
33
34
35
36
37
38
39
|
#include <iostream>
using namespace std;
int N, M;
int map[50][50], isV[50][50];
int r, c, d; //0북 1동 2남 3서
int ans = 1;
int dr[] = { -1,0,1,0 }, dc[] = { 0,1,0,-1 };
void solve() {
for (int i = 0; i < 4; i++) {
d = (d + 3) % 4; //왼쪽방향
int nr = r + dr[d], nc = c + dc[d];//다음 좌표
if (map[nr][nc] == 0 && isV[nr][nc] == 0) {
//청소가능
r = nr; c = nc; ans++; isV[nr][nc] = 1;
solve();
return;
}
}
int nd = (d + 2) % 4;
int nr = r + dr[nd], nc = c + dc[nd]; //후진
if (map[nr][nc] == 0) { r = nr; c = nc; solve(); }
else if(map[nr][nc]==1) return;
}
int main()
{
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];
isV[r][c] = 1; //현재위치 청소.
solve();
printf("%d\n", ans);
return 0;
}
|
cs |
'알고리즘 > 시뮬레이션' 카테고리의 다른 글
[백준]시험감독 (0) | 2019.07.11 |
---|---|
[백준]나무재테크 (0) | 2019.07.08 |
[백준]뱀 (0) | 2019.07.04 |
[백준]경사로_삼성기출 (0) | 2019.07.02 |
[시뮬레이션]주사위던지기 (0) | 2019.04.04 |