원웅이의 범죄행위를 도와주어야 하는 문제이다.
가장 왼쪽 열에서 가장 오른쪽 열까지 우상, 우, 우하로 움직이며 경로가 몇개가 되는지 구하는 문제이다.
각 경로는 서로 겹쳐서는 안된다.
경로를 찾을때는 DFS로 탐색을 한다.
현재 픽셀에서 우상, 우, 우하로 탐색하면서 재귀로 호출한다. - 우상, 우, 우하 탐색을 했을 때 전부 true가 없으면 false를 최종적으로 리턴하게 된다.
만약 현재 픽셀이 가장 오른쪽 열이라면, true를 리턴한다.
DFS를 짤 때, 재귀로 일단 생각하게 되는데 앞으로 풀어볼 때는 재귀가 아닌 코드로 한번 작성해보아야겠다. 재귀로 짤 경우 디버그가... 너무... 힘들다...
Visit[][] 배열은 Map 크기와 동일하게 만들어서 각 픽셀을 방문할때마다 true로 만든다.
초기 접근에서는 마지막까지 탐색해서 파이프가 완성될 경우만 true로 했었는데, 시간초과가 떴다.
다시 생각해보니 그 픽셀을 방문했고, 그 뒤로 탐색을 해서 파이프가 완성되지 않았으면, 그 픽셀은 어차피 그 뒤로 탐색 할 필요가 없었다.
그래서 일단 무조건 방문 가능한 조건이기만 하면 visit배열을 true로 만들게 하니 맞았다.
기본적인 탐색을 완성하면, 맵에서 가장 왼쪽 열 픽셀을 순회하며 탐색하면 된다.
#include <iostream>
#include <string>
struct pos
{
int y;
int x;
pos(int y, int x) : y(y), x(x) {}
};
int dx[] = {1, 1 ,1};
int dy[] = {-1, 0, 1};
std::string map[10000];
bool visited[10000][500];
int H, W;
bool getPipe(pos cur)
{
bool found = false;
if (cur.x == W - 1)
{
visited[cur.y][cur.x] = true;
return true;
}
for (int i = 0; i < 3 ; i++)
{
int ny = cur.y + dy[i];
int nx = cur.x + dx[i];
if (ny < 0 || ny > H - 1 || nx < 0 || nx > W - 1 || visited[ny][nx] || map[ny][nx] == 'x')
continue;
visited[cur.y][cur.x] = true; // 방문 할수 있기만 하면 체크 필요 -> 파이프 놓았어도 방문 할 필요 없고, 파이프 못 놓았어도, 이후 방문 필요 없음.
if (getPipe(pos(ny, nx)))
{
found = true;
break;
}
}
return found;
}
int main()
{
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> H >> W;
for (int i = 0 ; i < H; i++)
{
std::string inp;
std::cin >> inp;
map[i] += inp;
}
int pathCnt = 0;
for (int i = 0; i < H; i++)
{
if (getPipe(pos(i, 0)))
pathCnt++;
}
std::cout << pathCnt;
}
본 문제는 입출력이 많아, 입출력 속도 향상하는 코드 3줄을 main 문에 넣어야 한다. 그러고 나면 완성.
원래 전역을 잘 안쓰려고 하는 경향이 있는데, 알고리즘 문제를 풀면서 전역변수를 너무 많이 쓰는것 같다. 한 문제 문제같이 작은 코드는 괜찮은데, 이게 체화되어서 나중에 큰 프로젝트를 할 때도 써버리면 안될것 같다. 습관 들지 않게 조심할 필요가 있다.
오늘도 평온한 하루가 되길. 슨민.
'짜잘한 기록' 카테고리의 다른 글
백준 9527 1의 개수 세기 (0) | 2021.09.13 |
---|---|
백준 1987 알파벳 (0) | 2021.09.11 |
백준 1167 트리의 지름 (0) | 2021.09.09 |
백준 10026 적록색약 (0) | 2021.09.09 |
백준 1963 소수 경로 (0) | 2021.09.08 |