Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 백준 1049번
- 상월곡역 학원
- 월곡중 학원
- C++ 문자열
- 백준 2309번 일곱 난쟁이
- 운영체제
- 백준 K보다 큰 구간
- 백준 1049번 기타줄
- 상월곡동 학원
- 월곡역 학원
- 백준 14246번
- 백준 토마토
- 월곡동 학원추천
- 백준 10709
- c++ split
- DFS
- 성북구 학원
- 백준 9375번 패션왕 신해빈
- c++ 조합
- 서울사대부고 학원
- C++ 9996
- 백준 한국이 그리울 땐 서버에 접속하지
- C# 병합정렬
- 백준 dfs
- 관리형 학원
- 백준 패션왕 신해빈
- 월곡중학교 학원추천
- 백준 14246번 K보다 큰 구간
- 고정 소수점
- OS
Archives
- Today
- Total
키베이루's diary
[C++] 백준 2206번 벽 부수고 이동하기 본문
1) 문제설명
https://www.acmicpc.net/problem/2206
2206번: 벽 부수고 이동하기
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로
www.acmicpc.net
2) 아이디어
벽을 한 번만 부술 수 있기 때문에 처음에는 단순히 벽이 가로막고 있고 그 벽 다음이 뚫려있다면 벽을 뚫고 BFS를 순환하도록 구현하였는데 철저하게 틀린 답이었다. 먼저 벽을 뚫었을 때의 거리와 벽을 뚫지 않았을 때의 거리 중 뭐가 최소가 나오는지 알 수 없었고 벽을 먼저 뚫고 지나가면 나중에 나오는 벽을 뚫을 수없어 목표지점에 도달하지 못할 수도 있었다.
따라서 이 2가지를 생각하면서 구현을 해야 했다.
1. 벽을 뚫었을 때의 거리 VS 벽을 뚫지 않았을 때 거리
2. 처음에만 벽을 뚫는 것이 아닌 나중에도 벽을 뚫어야 한다.
이 두 가지를 해결하기 위해 3차원 배열을 사용하였다. [x좌표][y좌표][벽을 뚫었을 때/ 뚫지 않았을 때]
벽을 뚫었을 때와 뚫지 않았을 때의 저장공간이 다르기 때문에 앞의 2가지를 모두 해결할 수 있었다.
3) 코드
#include<iostream>
#include<queue>
#include<deque>
#include<string.h>
#include<math.h>
#include<cmath>
#include<stack>
#include<algorithm>
using namespace std;
int arr[1001][1001];
int visited[1001][1001][2]; // 방문표시
int range[1001][1001][2]; // 거리계산
int n, m, result;
typedef struct {
int x, y, w;
}st;
queue<st> q;
int bfs(int x, int y, int w) { // w가 0이면 아직 벽을 부수지 않았다.
q.push({ x, y, 0 }); // 처음 1,1,0
arr[x][y] = 0;
if (m == x && n == y) {
return 1;
}
while (!q.empty()) {
x = q.front().x;
y = q.front().y;
w = q.front().w;
q.pop();
if (x == n && y == m) {
return result = range[x][y][w] + 1;
}
int dx[] = { 0,0,-1,1 };
int dy[] = { 1,-1,0,0 };
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx<1 || ny<1 || nx>n || ny>m || arr[nx][ny] == -1) { // 범위를 벗어나거나 이미 방문한 곳일경우
continue;
}
else if (arr[nx][ny] == 0 && visited[nx][ny][w] == 0) { // 벽이 없고 방문하지 않은 곳일때
visited[nx][ny][w] = 1; // 방문표시
q.push({ nx,ny, w }); // 큐에 넣고
range[nx][ny][w] = range[x][y][w] + 1; // 범위 + 1
}
else if (arr[nx][ny] == 1 && w == 0) { // 벽이 있고 벽을 아직 뚫지 않았을때 (w가 0이 아니면 벽을 더 뚫지 못한다.)
visited[nx][ny][w+1] = 1; // 벽을 뚫었다는표시 (w가 0일때의 방문과 w가 1일때의 방문이 다르다)
q.push({ nx,ny,w+1}); // w = w+1 : w가 1이되므로 다음에 이 조건문을 통과하지 못하여 벽을 더뚫지 못함
range[nx][ny][w+1] = range[x][y][w] + 1; // 벽을 뚫었을때의 범위를 따로 계산한다.
}
}
}
return -1;
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%1d", &arr[i][j]);
}
}
cout << bfs(1, 1, 0) << endl;
}
'알고리즘 > BFS, DFS' 카테고리의 다른 글
[C++] 백준 11724번 연결 요소의 개수 (0) | 2022.06.16 |
---|---|
[C++] 백준 13023번 ABCDE (0) | 2022.06.14 |
[C++] 백준 16928번 뱀과 사다리 게임 (0) | 2022.06.11 |
[C++] 백준 7579번 토마토 (0) | 2022.06.11 |
[C++] 백준 1697번 숨바꼭질 (0) | 2022.06.10 |
Comments