ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 16933 벽 부수고 이동하기 3
    Problem Solving/Baekjoon Online Judge 2020. 3. 24. 12:57

    [문제이해]

    1. NxM 으로 표현되는 map이 있다. (0은 이동할 수 있는 공간이고, 1은 이동할 수 없는 벽이다.)

    2. 당신은 (1,1)에서 (N,M)위치로  최단 경로로 이동 해야한다.

    3. 이 문제에는 낮과 밤이 존재한다. 가장 처음에 이동할 때는 낮이고, 이동할 때마다 낮과 밤이 바뀐다.

    4. 이동하지 않고 같은 칸에 머무를 수 있는데, 이때도 낮과 밤이 바뀐다.

    3. map에서 벽을 만나면, 벽을 부술 수 있다. (벽은 최대 k개 만큼 부술 수 있다.)

    4. 단, 벽은 아침에만 부술 수 있다.

    5. map이 주어지고 N, M, k가 주어졌을 때 최단 경로를 구해내야 한다.

     

    [설계]

    1. 최단경로를 구하는 문제이므로 BFS를 사용하여 구현한다.

    2. BFS로 방문하는 정점의 정보는 4가지이다. (x좌표, y좌표, 벽을 부순 횟수, 낮(0) or 밤(1))

    3. Ex1) (0, 0, 0, 0) 은 (0,0)에서 벽을 0번 부쉈고 낮(0)인 상태이다.

    4. Ex2) (0, 0, 0, 1) 은 (0,0)에서 벽을 0번 부쉈고 밤(1)인 상태이다.

    5. Ex3) (4, 3, 5, 0) 은 (4,3)에서 벽을 5번 부쉈고 낮(0)인 상태이다.

    6. 즉, 정점의 상태는 4가지로 표현된다. 

    7. 따라서 BFS 방문처리 배열은 아래와 같은 4차원 배열을 사용한다.

        visited[x좌표][y좌표][벽을 부순 횟수][낮(0) or 밤(1)]

    8. 그 외 이동하지 않고 같은 칸에 머무를 수 있는 것, 벽은 아침에만 부술 수 있는 것, 벽은 최대 k개 만큼 부술 수 있는 것, 시작할때는 낮이고 이동할 때마다 낮과 밤이 바뀌는 것 등을 고려하여 BFS를 구현하면된다.

     

    [회고]

    - 정점의 상태를 정의하니까 풀기 수월했다.

    - 조건이 여러개라 복잡했지만 차근차근 풀어나갔다.

     

    [소스]

    #include<iostream>
    #include<queue>
    using namespace std;
    
    typedef struct {
    	int x, y, broken, day; 
    }pos;
    
    int n, m, k;
    int res = 1e9;
    int map[1000][1000];
    int visited[1000][1000][11][2];
    int dx[] = { -1,1,0,0,0 }, dy[] = { 0,0,-1,1,0 };
    
    void bfs() {
    	queue<pos> q;
    	visited[0][0][0][0] = 1;
    	q.push({ 0,0,0,0 });
    
    	while (!q.empty()){
    		int x = q.front().x, y = q.front().y;
    		int broken = q.front().broken, day = q.front().day;
    		int nextDay;
    
    		if (day == 0) nextDay = 1;
    		else nextDay = 0;
    
    		q.pop();
    
    		if (x == n - 1 && y == m - 1) {
    			res = min(res, visited[x][y][broken][day]);
    		}
    
    		for (int i = 0; i < 5; i++) {
    			int nx = x + dx[i], ny = y + dy[i];
    			if (nx >= n || nx < 0 || ny >= m || ny < 0) continue;
    			
    			if(x == nx && y== ny){
    				if (visited[nx][ny][broken][nextDay] == 0) {
    					visited[nx][ny][broken][nextDay] = visited[nx][ny][broken][day] + 1;
    					q.push({ nx,ny,broken,nextDay });
    				}
    			}
    			else if (map[nx][ny] == 0 && visited[nx][ny][broken][nextDay] == 0) {
    				visited[nx][ny][broken][nextDay] = visited[x][y][broken][day] + 1;
    				q.push({ nx, ny, broken, nextDay });
    			}
    			else if (map[nx][ny] == 1 && visited[nx][ny][broken + 1][nextDay] == 0) {
    				if (day == 1) continue;
    				if (broken + 1 > k) continue;
    				visited[nx][ny][broken + 1][nextDay] = visited[x][y][broken][day] + 1;
    				q.push({ nx, ny, broken + 1,nextDay });
    			}
    		}
    	}
    }
    
    int main() {
    
    	cin >> n >> m >> k;
    
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < m; j++) {
    			scanf_s("%1d", &map[i][j]);
    		}
    	}
    
    	bfs();
    
    	if (res == 1e9)
    		cout << -1;
    	else
    		cout << res;
    
    	return 0;
    }

    'Problem Solving > Baekjoon Online Judge' 카테고리의 다른 글

    [백준] 1038 감소하는 수  (0) 2020.04.15
    [백준] 16234 인구이동  (0) 2020.03.26
    [백준] 17141 연구소 2  (0) 2020.03.26
    [백준] 16197 두 동전  (0) 2020.03.08
    [백준] 13460 구슬 탈출 2  (0) 2020.03.06

    댓글

Designed by Tistory.