읽기 전
- 해당 게시물은 작성자가 학습한 내용을 정리 및 요약 목적으로 작성되었으므로 오역 및 오개념이 있을 수 있습니다.
- 바로잡기 위한 의견을 제시해주시면 매우 감사하겠습니다.
Rat in Maze
왼쪽 위가 시작점은 N*N 이진 행렬이 주어졌다고 하자. 도착 지점은 오른쪽 아래이며 좌표로 표현하면 시작점: maze[0][0]
, 도착점: maze[N-1][N-1]
이 된다. 쥐는 시작점에서 출발하여 도착점까지 가야 하는데 오직 아래 방향과 우측 방향으로만 이동할 수 있다. 주어진 이진 행렬에서 0은 막혀있는 블록, 1은 경로로 사용할 수 있는 블록을 의미한다. 그렇다면 쥐가 maze의 시작점에서 도착점까지 갈 수 있는 경로를 출력하자.
Backtracking
- 0으로 채워진 경로 행렬을 생성한다.
- 쥐의 좌표와 전체 지도, 경로를 기록할 행렬을 받는 재귀함수를 생성한다.
- 만약 좌표가 맵을 벗어나거나 유효하지 않은 좌표라면 넘어간다.
- 가능한 좌표일 경우 해당 좌표에 1을 체크하고 현재 좌표가 도착지점인지 검사한다. 만약 도착지점이라면 경로를 출력한다.
- (i+1, j), (i, j+1) 좌표에 대해 계속 재귀 탐색을 진행한다.
- 만약 이후 단계에 문제가 생기면 (i, j) 좌표를 다시 0으로 초기화한다.
C코드
#include <stdio.h>
#define N 4
// 메인 함수에 사용할 재귀문 사전 정의
bool solveMazeUtil(int x, int y, int sol[N][N], int maze[N][N]);
// 해답 도출 시 전체 경로 출력
void printSolution(int sol[N][N])
{
for (int x = 0; x < N; x++)
{
for (int y = 0; y < N; y++)
{
printf("%d ", sol[x][y]);
}
printf("\n");
}
}
// 좌표가 제약조건을 만족하는 지 검사
int isSafe(int x, int y, int maze[N][N])
{
// x, y가 맵을 벗어나는 지, 해당 좌표가 경로로 사용될 수 있는 지 검사
return (0 <= x && x < N && 0 <= y && y < N && maze[x][y] == 1);
}
// 결과를 반환하는 함수
bool solveMaze(int maze[N][N])
{
int sol[N][N]; // 경로 배열 선언
for (int x = 0; x < N; x++)
{
for (int y = 0; y < N; y++)
{
sol[x][y] = 0; // 전체 경로 초기화
}
}
// 만약 성립하는 경로가 존재하면
if (solveMazeUtil(0, 0, sol, maze) == true)
{
printSolution(sol); // 전체 경로 출력
return true;
}
else // 성립하는 경로가 없으면
{
printf("There's no Solution!"); // 답없음 출력
return false;
}
}
// 재귀함수 정의
bool solveMazeUtil(int x, int y, int sol[N][N], int maze[N][N])
{
if (x == N-1 && y == N-1 && maze[x][y] == 1)
{ // 만약 끝점에 도달하였고 그 노드가 도착점이라면
sol[x][y] = 1; // 도착점 좌표의 경로에 1 체크
return true; // 탐색 종료
}
if (isSafe(x, y, maze)) // 해당 좌표가 안전하면
{
sol[x][y] = 1; // 경로에 사용되었음을 체크
if (solveMazeUtil(x+1, y, sol, maze))
{ // 우측 이동 시 문제가 없다면 이전 단계에 true 반환
return true;
}
else if (solveMazeUtil(x, y+1, sol, maze))
{ // 하단 이동 시 문제가 없다면 이전 단계에 true 반환
return true;
}
else // 모든 방향을 시도했음에도 성립하는 경로가 없다면
{
sol[x][y] = 0; // backtracking
return false; // 이전 단계에 false 반환
}
}
return false; // 안전한 좌표 없다면 false 반환
}
int main()
{
int maze[N][N] = { { 1, 0, 0, 0 },
{ 1, 1, 0, 1 },
{ 0, 1, 0, 0 },
{ 1, 1, 1, 1 } };
solveMaze(maze);
return 0;
}
Python 코드
def printSolution(sol):
for i in sol:
for j in i:
print(str(j) + " ", end = "") # 이쁘게 출력하기 위함
print("") # 개행
def isSafe(x, y, maze): # 조건검사하는 함수
return (0 <= x < N and 0 <= y < N and maze[x][y] == 1)
def solveMaze(maze):
sol = [[0 for j in range(4)] for i in range(4)]
if solveMazeUtil(0, 0, sol, maze) == False:
print("There's no Solution!")
return False
else:
printSolution(sol)
return True
def solveMazeUtil(x, y, sol, maze):
if x == N-1 and y == N-1 and maze[x][y] == 1:
sol[x][y] = 1 # 탐색이 끝나면 도착지점에 1 표시 후 종료
return True
if isSafe(x, y, maze): # 탐색 좌표가 안전하면
sol[x][y] = 1 # 체크
if solveMazeUtil(x+1, y, sol, maze):
return True # 우측으로 이동 시 이후에도 문제 없으면 True
elif solveMazeUtil(x, y+1, sol, maze):
return True # 하단으로 이동 시 이후에도 문제 없으면 True
else:
sol[x][y] = 0 # backtracking
return False # 이전 단계로 퇴각
maze = [ [1, 0, 0, 0],
[1, 1, 0, 1],
[0, 1, 1, 0],
[1, 1, 1, 1] ]
N = 4
solveMaze(maze)
C++ 코드
c++ 코드는 C 코드와 문법을 비교했을 때 출력문을 제외하고는 없어서 주석을 생략하였다.
#include <bits/stdc++.h>
using namespace std;
#define N 4
bool solveMazeUtil(int x, int y, int sol[N][N], int maze[N][N]);
void printSolution(int sol[N][N])
{
for (int x = 0; x < N; x++)
{
for (int y = 0; y < N; y++)
{
cout << sol[x][y] << " ";
}
cout << endl;
}
}
int isSafe(int x, int y, int maze[N][N])
{
return (0 <= x < N && 0 <= y < N && maze[x][y] == 1);
}
bool solveMaze(int maze[N][N])
{
int sol[N][N];
for (int x = 0; x < N; x++)
{
for (int y = 0; y < N; y++)
{
sol[x][y] = 0;
}
}
if (solveMazeUtil(0, 0, sol, maze))
{
printSolution(sol);
return true;
}
else
{
cout << "There's no Solution" << endl;
return false;
}
}
bool solveMazeUtil(int x, int y, int sol[N][N], int maze[N][N])
{
if (x == N-1 && y == N-1 && maze[x][y] == 1)
{
sol[x][y] = 1;
return true;
}
if (isSafe(x, y, maze))
{
sol[x][y] = 1;
if (solveMazeUtil(x+1, y, sol, maze))
{
return true;
}
else if (solveMazeUtil(x, y+1, sol, maze))
{
return true;
}
else
{
sol[x][y] = 0;
return false;
}
}
return false;
}
int main()
{
int maze[N][N] = { { 1, 0, 0, 0 },
{ 1, 1, 0, 1 },
{ 0, 1, 0, 0 },
{ 1, 1, 1, 1 } };
solveMaze(maze);
return 0;
}
참고자료
'Algorithms > Geeks for Geeks' 카테고리의 다른 글
Backtracking | N Queen Problem (0) | 2020.09.24 |
---|---|
Backtracking | The Knight’s tour problem (0) | 2020.09.23 |
Backtracking | Write a program to print all permutations of a given string (0) | 2020.09.18 |
Analysis of Algorithms | Performance of loops (A caching question) (0) | 2020.09.17 |
Analysis of Algorithms | Time Complexity of Loop with Powers (0) | 2020.09.17 |