https://www.acmicpc.net/problem/6593
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()
'백준 PS일지 > DFS&BFS' 카테고리의 다른 글
[백준/Swift] 17086 : 아기 상어2 (0) | 2022.07.10 |
---|---|
[백준/Swift] 18405 : 경쟁적 전염 (0) | 2022.07.05 |
[백준/Swift] 5014 : 스타트링크 (0) | 2022.07.02 |
[백준/Swift] 16234 : 인구이동 (0) | 2022.07.02 |