본문 바로가기

백준 PS일지/DFS&BFS

[백준/Swift] 6593 : 상범 빌딩

 

 

 

https://www.acmicpc.net/problem/6593

 

6593번: 상범 빌딩

당신은 상범 빌딩에 갇히고 말았다. 여기서 탈출하는 가장 빠른 길은 무엇일까? 상범 빌딩은 각 변의 길이가 1인 정육면체(단위 정육면체)로 이루어져있다. 각 정육면체는 금으로 이루어져 있어

www.acmicpc.net

 


6593 : 상범 빌딩 / 문제 소개

 

이 문제는 토마토와 상당히 유사한 문제입니다. 

상범이는 " S " 지점에서 " . " 땅을 거쳐 " E "에 도착하면, 도착 하기까지 x분을 

Escaped in x minute(s).

로 출력하는 문제입니다.

 

만일 탈출을 하지 못할 경우

Trapped!

출력을 하면 됩니다.

 


풀이 과정

 

주어진 입력에서 "#"은 볼 필요 없습니다.

bfs탐색을 통해 시작지점에서 E지점까지 탐색을 하면 됩니다.

이때 상 하 좌 우 + 위층, 아래층 을 탐색해야하고


  
let direction = [(-1,0,0),(1,0,0),(0,1,0),(0,-1,0),(0,0,-1),(0,0,1)]

next 좌표를 탐색 할 때

위, 아래층 까지도 0과 주어진 층 수 이상의 층을 탐색하지 못하도록 하는 것이 중요합니다.


  
if nx < 0 || nx > info.width - 1 ||
ny < 0 || ny > info.height - 1 ||
nFloor < 0 || nFloor > info.floor - 1
{
continue
}

저는 queue를 사용해서 queue에 현재 x좌표, y좌표, 현재 탐색 중인 층을 저장하는 Element를 선언 후 저장해서

index를 통해 더이상 탐색할 수 없을 때까지 탐색해 나갔습니다.


  
typealias Element = (x: Int, y : Int, floor : Int)
var queue = [Element]()
var index = 0

 


코드 구현


  
import Foundation
/**
* @param Element : 현재 탐색중인 x지점, y지점, 층 저장
* @param direction : 좌,우,상,하,아래,위 탐색하는 next좌표 구하기 전 direction입니다.
*/
typealias Element = (x: Int, y : Int, floor : Int)
let direction = [(-1,0,0),(1,0,0),(0,1,0),(0,-1,0),(0,0,-1),(0,0,1)]
/**
* 빌딩의 주요 정보가 들어있습니다.
* @param width : 특정 층 빌딩 가로
* @param height : 특정 층 빌딩 세로
* @param floor : 빌딩 전체 층 수
*/
class mapInfo
{
let width : Int
let height : Int
let floor : Int
init()
{
let input = readLine()!.split(separator: " ").map{Int(String($0))!}
floor = input[0]
height = input[1]
width = input[2]
}
}
/**
* 상범이의 탈출 과정!
* 중간에 return하지못할 경우 Trapped!
*
* @param queue : 탐색 가능한 좌표 저장
* @param index : queue탐색하기 위한 index
*
* 탐색 지점이 "E"인 경우 현재 분 저장 후 return
*/
func escape(_ info : mapInfo, _ start : Element, _ end : Element, _ res : inout String, _ building : [[[String]]], _ visited : inout [[[Int]]])
{
var queue = [Element]()
var index = 0
queue.append(start)
visited[start.floor][start.y][start.x] = 1
while(queue.count != index)
{
let (curX,curY,curFloor) = queue[index]
index += 1
for (dx,dy,dFloor) in direction
{
let (nx,ny,nFloor) = (curX+dx, curY+dy, curFloor+dFloor)
if nx < 0 || nx > info.width - 1 || ny < 0 || ny > info.height - 1 || nFloor < 0 || nFloor > info.floor - 1
{
continue
}
if building[nFloor][ny][nx] == "E"
{
res += "Escaped in \(visited[curFloor][curY][curX]) minute(s).\n"
return
}
if visited[nFloor][ny][nx] == 0 && building[nFloor][ny][nx] == "."
{
visited[nFloor][ny][nx] = visited[curFloor][curY][curX] + 1
queue.append((nx,ny,nFloor))
}
}
}
res += "Trapped!\n"
}
/**
* @param res : 결과 저장
*/
func BOJ_6593()
{
var res = ""
/**
* @param info : 맵 정보
* @param building : 빌딩 정보
* @param visited : bfs 탐색을 통해 탐색중인 x분 갱신
* @param start : 상범이 시작 위치 (x , y , i 층)
* @param end : 상범이 도착 위치 (x , y , i 층)
*/
while true
{
let info = mapInfo()
var building = Array(repeating: [[String]](), count: info.floor)
var visited = Array(repeating: Array(repeating: Array(repeating: 0, count: info.width), count: info.height), count: info.floor)
var start = (0,0,0)
var finish = (0,0,0)
if info.floor == 0 { break }
for i in 0..<info.floor
{
building[i] =
{
var tempMap = Array(repeating: [String](), count: info.height)
for y in 0..<info.height
{
let mapLine = readLine()!.map{String($0)}
tempMap[y] = mapLine
for x in 0..<info.width
{
if tempMap[y][x] == "S"
{
start = (x,y,i)
}
if tempMap[y][x] == "E"
{
finish = (x,y,i)
}
}
}
return tempMap
}()
//매 층 이후에 엔터 있어서 readLine()처리
readLine()!
}
escape(info, start, finish, &res, building, &visited)
}
print(res)
}
BOJ_6593()

 

728x90