문제 : https://www.acmicpc.net/problem/14503

 

서론

시뮬레이션 문제.

 


풀이

시뮬레이션 문제이므로 문제가 시키는대로 잘 따라간다.

 

편의를 위해서 문제를 한가지 수정한다.

문제에서는 d가 0인 경우에는 북쪽을, 1인 경우에는 동쪽을, 2인 경우에는 남쪽을, 3인 경우에는 서쪽이라고 하는데

0은 북, 1은 서, 2는 남, 3은 동으로 수정했다.

청소기가 오로지 왼쪽으로만 회전을 하는데 왼쪽으로 회전하면 d가 1 증가하므로 (d+1)%4 를 쓰기 위해서다.

(d+1)%4 는 d가 0, 1, 2, 3, 0, 1, 2 ...로 0~3만 가지도록 한다.

문제를 수정했으므로 방향을 입력받을 때도 수정해줘야한다.

 

dy[4] = { -1, 0, 1, 0 }
dx[4] = { 0, -1, 0, 1 }

위와 같이 4개의 방향(북, 서, 남, 동)을 선언해주고

 

왼쪽 방향은 (d + 1) % 4

뒷 방향은 (d + 2) % 4

 

왼쪽방향으로 이동하는 방법은

y += dy[(d + 1) % 4]
x += dx[(d + 1) % 4]

 

청소할때는 지도를 2로 만들어주면

청소를 했거나 벽일때 조건식을 map[y][x] > 0으로 만들어줄 수 있어서 간편하다.

 

그리고 구현하면 된다.

while(1){ // 청소기는 계속 움직여야한다.
    if(동서남북 모두 벽이거나 청소했다) { 
    	if(뒤가 벽이다) break; // d
        else 후진; // c
    }
    else if(왼쪽이 청소를 안했다){ // a
    	방향 왼쪽으로
        왼쪽으로 이동
        청소
        청소구역++
    }
    else if(왼쪽이 청소를 했거나 벽이다){ // b
    	방향 왼쪽으로
    }
}

주의할점은 문제의 a, b, c, d순서가 아닌 d, c, a, b순서란 것이다. a, b, c, d 순서로 하면 동서남북 모두 청소를 했거나 벽일때 b에서 무한루프에 빠진다.

 


구현

// c++

#include <iostream>

using namespace std;

int map[50][50];
int sum;
int dy[4] = { -1, 0, 1, 0 };
int dx[4] = { 0, -1, 0, 1 };
int n, m;

int main() {

	cin >> n >> m;
	int y, x, dir;
	cin >> y >> x >> dir;
	if (dir == 1) dir = 3;
	else if (dir == 3) dir = 1;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> map[i][j];
		}
	}

	map[y][x] = 2; // 청소
	sum++;

	while (1) {
		//cout << y << x << endl;
		int left = (dir + 1) % 4; // 왼쪽방향
		int back = (dir + 2) % 4; // 뒷방향
		//cout << dir << left << back << endl;
		if (map[y][x - 1] > 0 && map[y][x + 1] > 0 && map[y + 1][x] > 0 && map[y - 1][x] > 0) { 
			if (map[y + dy[(dir + 2) % 4]][x + dx[(dir + 2) % 4]] == 1) break; // d
			else { // c
				y += dy[back];
				x += dx[back];
			}
			
		}
		else if (map[y + dy[left]][x + dx[left]] == 0) { // a
			dir = left;
			y += dy[left];
			x += dx[left];
			map[y][x] = 2;
			sum++;
		}
		else if (map[y + dy[left]][x + dx[left]] > 0) { // b
			dir = left;
		}
	}

	cout << sum;
}