문제

적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다.

크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은 색상이라 한다)

예를 들어, 그림이 아래와 같은 경우에

RRRBB
GGBBB
BBBRR
BBRRR
RRRRR

적록색약이 아닌 사람이 봤을 때 구역의 수는 총 4개이다. (빨강 2, 파랑 1, 초록 1) 하지만, 적록색약인 사람은 구역을 3개 볼 수 있다. (빨강-초록 2, 파랑 1)

그림이 입력으로 주어졌을 때, 적록색약인 사람이 봤을 때와 아닌 사람이 봤을 때 구역의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. (1 ≤ N ≤ 100)

둘째 줄부터 N개 줄에는 그림이 주어진다.

출력

적록색약이 아닌 사람이 봤을 때의 구역의 개수와 적록색약인 사람이 봤을 때의 구역의 수를 공백으로 구분해 출력한다.

내가 푼 풀이

- 해당 그림이 주어지면, 색의 구역의 수를 출력한다.

- 적록색약은 R,G 를 구분하지못하므로, 그래프를 탐색할 때, R과G는 같다고 판단하고 탐색한다.

- 단순히 구역의 수를 구하는 문제이므로 BFS, DFS 둘다 사용 가능하지만, DFS를 사용했다.

 

import Foundation

var n = Int(readLine()!)!
var arr = [[String]]()
var result = [Int]()

// dif 는 적록색약인지 판단
var dif = false
// x y 방향
var dx = [1,0,-1,0]
var dy = [0,1,0,-1]

// 그립을 배열에 입력
for i in 0..<n {
    var input = Array(readLine()!).map{ String($0) }
    arr.append(input)
}

// 결과 두가지 호출을 위한 result 배열
// 단순히 구역의 수를 구하기위하므로 DFS 이용
while result.count != 2 {
    var needVisitQueue = [(x: Int, y: Int)]()
    var count = 0
    var copyArr = arr
    // 정상인 사람의 구역 수 를 넣으면 색약인사람을 검사
    if result.count == 1 {
        dif = true
    } else {
        dif = false
    }
    // 정상인 사람의 구역의 개수 구하기
    if !dif {
        for i in 0..<copyArr.count {
            for j in 0..<copyArr.count {
                if copyArr[i][j] == "X" { continue }
                needVisitQueue.append((x: j, y: i))
                var check = copyArr[i][j]
                while !needVisitQueue.isEmpty {
                    var node = needVisitQueue.removeLast()
                    copyArr[node.y][node.x] = "X"
                    
                    for k in 0..<4 {
                        var cx = node.x + dx[k]
                        var cy = node.y + dy[k]
                        
                        if (cx >= 0 && cx < n) && (cy >= 0 && cy < n) {
                            if copyArr[cy][cx] == check {
                                needVisitQueue.append((x: cx, y: cy))
                            }
                        }
                    }
                }
                count += 1
            }
        }
        result.append(count)
    } else {
        // 적록색약인 사람의 구역의 개수 구하기
        for i in 0..<copyArr.count {
            for j in 0..<copyArr.count {
                if copyArr[i][j] == "X" { continue }
                needVisitQueue.append((x: j, y: i))
                var check = copyArr[i][j]
                while !needVisitQueue.isEmpty {
                    var node = needVisitQueue.removeLast()
                    copyArr[node.y][node.x] = "X"
                    
                    for k in 0..<4 {
                        var cx = node.x + dx[k]
                        var cy = node.y + dy[k]
                        
                        if (cx >= 0 && cx < n) && (cy >= 0 && cy < n) {
                            if check == "R" || check == "G" {
                                if copyArr[cy][cx] == "R" || copyArr[cy][cx] == "G" {
                                    needVisitQueue.append((x: cx, y: cy))
                                }
                            } else if copyArr[cy][cx] == check {
                                needVisitQueue.append((x: cx, y: cy))
                            }
                        }
                    }
                }
                count += 1
            }
        }
        result.append(count)
    }
}

print(result.map{String($0)}.joined(separator: " "))

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-18310 안테나 Swift  (0) 2023.06.04
BOJ-2565 전깃줄 Swift  (0) 2023.06.04
BOJ-1969 DNA Swift  (0) 2023.06.02
BOJ-11048 이동하기 Swift  (0) 2023.06.02
BOJ-1753 최단경로 Swift  (0) 2023.06.01

문제

DNA란 어떤 유전물질을 구성하는 분자이다. 이 DNA는 서로 다른 4가지의 뉴클레오티드로 이루어져 있다(Adenine, Thymine, Guanine, Cytosine). 우리는 어떤 DNA의 물질을 표현할 때, 이 DNA를 이루는 뉴클레오티드의 첫글자를 따서 표현한다. 만약에 Thymine-Adenine-Adenine-Cytosine-Thymine-Guanine-Cytosine-Cytosine-Guanine-Adenine-Thymine로 이루어진 DNA가 있다고 하면, “TAACTGCCGAT”로 표현할 수 있다. 그리고 Hamming Distance란 길이가 같은 두 DNA가 있을 때, 각 위치의 뉴클오티드 문자가 다른 것의 개수이다. 만약에 “AGCAT"와 ”GGAAT"는 첫 번째 글자와 세 번째 글자가 다르므로 Hamming Distance는 2이다.

우리가 할 일은 다음과 같다. N개의 길이 M인 DNA s1, s2, ..., sn가 주어져 있을 때 Hamming Distance의 합이 가장 작은 DNA s를 구하는 것이다. 즉, s와 s1의 Hamming Distance + s와 s2의 Hamming Distance + s와 s3의 Hamming Distance ... 의 합이 최소가 된다는 의미이다.

입력

첫 줄에 DNA의 수 N과 문자열의 길이 M이 주어진다. 그리고 둘째 줄부터 N+1번째 줄까지 N개의 DNA가 주어진다. N은 1,000보다 작거나 같은 자연수이고, M은 50보다 작거나 같은 자연수이다.

출력

첫째 줄에 Hamming Distance의 합이 가장 작은 DNA 를 출력하고, 둘째 줄에는 그 Hamming Distance의 합을 출력하시오. 그러한 DNA가 여러 개 있을 때에는 사전순으로 가장 앞서는 것을 출력한다.

내가 푼 풀이

- 주어진 문자열들의 열들을 비교해가며, 가장 많은 문자를 따온다.

- 만약 해당 열에 여러개의 문자의 수가 같다면, 사전순으로 앞에 있는 문자를 따온다.

- Hamming Distance는 해당 문자와 다른 문자의 갯수다. 

- 문자를 따올때, 해당문자와 다른 문자의 개수를 더해주면 주어진 문자열들과 Hamming Distance의 합이 가장 작은 DNA가 되고,

그 합이 이전에 더해진 수와 같다.

 

코드로 구현하면 다음과 같다.

 

import Foundation

let input = readLine()!.split(separator: " ").map{ Int($0)! }
var arr = [[String]]()
var str = ""
var hd = 0

// 문자열 입력
for i in 0..<input[0] {
    arr.append(Array(readLine()!).map{String($0)})
}

// 주어진 문자열의 열을 모두 비교
// 문자와 문자의 개수를 구한다.
// 문자를 배열에 저장해 오름차순으로 정렬하면 0번째 원소가 사전순으로 가장 앞선다.
// 해당 문자와 다른문자의 개수를 더해가면 주어진 문자열들과 Hamming Distance의 합이 최소가 된다.
for i in 0..<input[1] {
    var dict = [String: Int]()
    for j in 0..<input[0] {
        if dict[arr[j][i]] == nil {
            dict[arr[j][i]] = 1
        } else {
            dict[arr[j][i]]! += 1
        }
    }
    var hdNum = 0
    var s = [String]()
    for (key,value) in dict {
        if value == dict.values.max()! {
            hdNum = input[0] - value
            s.append(key)
        }
    }
    s.sort{ $0 < $1}
    str += s[0]
    hd += hdNum
}

print(str)
print(hd)

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-2565 전깃줄 Swift  (0) 2023.06.04
BOJ-10026 적록색약 Swift  (0) 2023.06.02
BOJ-11048 이동하기 Swift  (0) 2023.06.02
BOJ-1753 최단경로 Swift  (0) 2023.06.01
BOJ-14502 연구소 Swift  (0) 2023.06.01

문제

준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다.

준규는 현재 (1, 1)에 있고, (N, M)으로 이동하려고 한다. 준규가 (r, c)에 있으면, (r+1, c), (r, c+1), (r+1, c+1)로 이동할 수 있고, 각 방을 방문할 때마다 방에 놓여져있는 사탕을 모두 가져갈 수 있다. 또, 미로 밖으로 나갈 수는 없다.

준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수의 최댓값을 구하시오.

입력

첫째 줄에 미로의 크기 N, M이 주어진다. (1 ≤ N, M ≤ 1,000)

둘째 줄부터 N개 줄에는 총 M개의 숫자가 주어지며, r번째 줄의 c번째 수는 (r, c)에 놓여져 있는 사탕의 개수이다. 사탕의 개수는 0보다 크거나 같고, 100보다 작거나 같다.

출력

첫째 줄에 준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수를 출력한다.

내가 푼 풀이

- N x M 크기의 배열이 주어지면 (1,1) 에서 (N, M)으로 이동할 때 오른쪽, 아래, 오른쪽대각선 방향으로만 이동한다.

- dp배열을 (n+1) x (m+1) 크기만큼 선언해서 dp[i][j] = i, j까지의 사탕 개수 최댓값으로 저장한다.

- 이는 dp[i][j] = max( dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + arr[i][j]로 나타낼 수 있다.

 

코드로 구현하면 다음과 같다.

 

import Foundation

let input = readLine()!.split(separator: " ").map{ Int($0)! }
var dp = Array(repeating: Array(repeating: 0, count: input[1]+1), count: input[0]+1)
var arr = Array(repeating: Array(repeating: 0, count: input[1]+1), count: input[0]+1)

// 사탕 미로 입력
for i in 0..<input[0] {
    var a = readLine()!.split(separator: " ").map{ Int($0)! }
    for j in 0..<a.count {
        arr[i+1][j+1] = a[j]
    }
}

// dp 입력
dp[1][1] = arr[1][1]
for i in 1...input[0] {
    for j in 1...input[1] {
        dp[i][j] = max(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + arr[i][j]
    }
}
print(dp[input[0]][input[1]])

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-10026 적록색약 Swift  (0) 2023.06.02
BOJ-1969 DNA Swift  (0) 2023.06.02
BOJ-1753 최단경로 Swift  (0) 2023.06.01
BOJ-14502 연구소 Swift  (0) 2023.06.01
BOJ-2810 컵홀더 Swift  (0) 2023.06.01

문제

방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 10 이하의 자연수이다.

입력

첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.

출력

첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다.

내가 푼 풀이

- 처음에는 BFS로 시작지점부터 가중치를 더해가며 가중치 최솟값을 갱신해나가는 방법을 사용했다.

- 역시나 시간초과가 떠서, 더빠른 우선순위큐와 다익스트라 알고리즘을 이용했다.

- 스위프트는 우선순위큐를 직접 구현해야한다.

- 또한 배열의 접근보다 튜플을 이용하면 좀 더 빠르다고 하니 튜플 사용하는데 익숙해져야겠다.

 

 

< 시간초과가 난 코드 >

//var input = readLine()!.split(separator: " ").map{ Int($0)! }
//var k = Int(readLine()!)!
//var graph = [Int: [[Int]]]()
//var dp = Array(repeating: -1, count: input[0]+1)
//dp[k] = 0
//
//for i in 0..<input[1] {
//    var inp = readLine()!.split(separator: " ").map{ Int($0)! }
//    if graph[inp[0]] == nil {
//        graph[inp[0]] = [[inp[1],inp[2]]]
//    } else {
//        var b = false
//        for i in 0..<graph[inp[0]]!.count {
//            if graph[inp[0]]![i][0] == inp[1] {
//                b = true
//                if graph[inp[0]]![i][1] > inp[2] {
//                    graph[inp[0]]![i][1] = inp[2]
//                }
//            }
//        }
//        if !b {
//            graph[inp[0]]!.append([inp[1],inp[2]])
//        }
//    }
//}
//
//var visitedQueue = [Int]()
//var needVisitQueue = [k]
//var nums = [Int]()
//
//while !needVisitQueue.isEmpty {
//    var node = needVisitQueue.removeFirst()
//    var num = 0
//    if nums.count != 0 { num = nums.removeFirst() }
//    if visitedQueue.contains(node) {
//        if dp[node] > num {
//            dp[node] = num
//        }
//    } else {
//        dp[node] = num
//    }
//    visitedQueue.append(node)
//    if graph[node] != nil {
//        for i in 0..<graph[node]!.count {
//            needVisitQueue.append(graph[node]![i][0])
//            nums.append(graph[node]![i][1] + num)
//        }
//    }
//}
//
//for i in 1..<dp.count {
//    if dp[i] == -1 {
//        print("INF")
//    } else {
//        print(dp[i])
//    }
//}

 

 

import Foundation

struct Heap<T: Comparable> {
    private var elements = [T]()
    private let sortFunction: (T,T) -> Bool
    
    var isEmpty: Bool {
        return self.elements.count == 1
    }
    var peek: T? {
        if self.elements.isEmpty { return nil}
        return self.elements[1]
    }
    
    var count: Int {
        return self.elements.count - 1
    }
    
    init(elements: [T] = [], sortFunction:@escaping (T,T) -> Bool) {
        if !elements.isEmpty {
            self.elements = [elements.first!] + elements
        } else {
            self.elements = elements
        }
        self.sortFunction = sortFunction
        
        if self.elements.count > 1 {
            buildHeap()
        }
    }
    
    func leftChild(of index: Int) -> Int {
        return index * 2
    }
    func rightChild(of index: Int) -> Int {
        return index * 2 + 1
    }
    func parent(of index: Int) -> Int {
        return index / 2
    }
    
    mutating func swimUp(from index: Int) {
        var index = index
        while index != 1 && self.sortFunction(self.elements[index], self.elements[self.parent(of: index)]) {
            self.elements.swapAt(index, self.parent(of: index))
            index = self.parent(of: index)
        }
    }
    
    mutating func insert(node: T) {
        if self.elements.isEmpty {
            self.elements.append(node)
            return
        }
        self.elements.append(node)
        self.swimUp(from: self.elements.endIndex - 1)
    }
    
    mutating func diveDown(from index: Int) {
        var higherPriority = index
        let leftIndex = self.leftChild(of: index)
        let rightIndex = self.rightChild(of: index)
        
        if leftIndex < self.elements.endIndex && self.sortFunction(self.elements[leftIndex], self.elements[higherPriority]) {
            higherPriority = leftIndex
        }
        if rightIndex < self.elements.endIndex && self.sortFunction(self.elements[rightIndex], self.elements[higherPriority]) {
            higherPriority = rightIndex
        }
        
        if higherPriority != index {
            self.elements.swapAt(index, higherPriority)
            self.diveDown(from: higherPriority)
        }
    }
    
    mutating func buildHeap() {
        for index in (1...self.elements.count / 2).reversed() {
            self.diveDown(from: index)
        }
    }
    
    mutating func remove() -> T? {
        if self.elements.isEmpty { return nil }
        self.elements.swapAt(1, self.elements.endIndex - 1)
        let deleted = self.elements.removeLast()
        self.diveDown(from: 1)
        
        return deleted
    }
}

struct PriorityQueue<T: Comparable> {
    var heap: Heap<T>
    
    init( elements: [T] = [], sort: @escaping (T,T) -> Bool) {
        heap = Heap(elements: elements, sortFunction: sort)
    }
    var count: Int {
        return heap.count
    }
    var isEmpty: Bool {
        return heap.isEmpty
    }
    
    func top() -> T? {
        return heap.peek
    }
    
    mutating func clear() {
        while !heap.isEmpty {
            heap.remove()
        }
    }
    
    mutating func pop() -> T? {
        return heap.remove()
    }
    mutating func push(element: T) {
        heap.insert(node: element)
    }
}
struct Node: Comparable {
    static func < (lhs: Node, rhs: Node) -> Bool {
        lhs.cost < rhs.cost
    }
    
    init(_ node: Int,_ cost: Int) {
        self.node = node
        self.cost = cost
    }
    let node: Int
    let cost: Int
}

var input = readLine()!.split(separator: " ").map{ Int($0)! }
var k = Int(readLine()!)!
var arr = Array(repeating: Array<(Int, Int)>(), count: input[0] + 1)
var dp = Array(repeating: Int.max, count: input[0]+1)
dp[k] = 0
for i in 0..<input[1] {
    let inp = readLine()!.split(separator: " ").map{ Int($0)! }
    let (s, a, c) = (inp[0], inp[1], inp[2])
    arr[s].append((a, c))
}

func dijkstra(start: Int) {
    var pq = PriorityQueue<Node>(sort: < )
    pq.push(element: Node(start, 0))
    pq.push(element: Node(start, 0))
    
    while !pq.isEmpty {
        let nd = pq.pop()!
        if dp[nd.node] < nd.cost {
            continue
        }
        
        for next in arr[nd.node] {
            let cost = nd.cost + next.1
            
            if cost < dp[next.0] {
                dp[next.0] = cost
                pq.push(element: Node(next.0, cost))
            }
        }
    }
}

dijkstra(start: k)

for i in 1..<dp.count {
    if dp[i] == Int.max {
        print("INF")
    } else {
        print(dp[i])
    }
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-1969 DNA Swift  (0) 2023.06.02
BOJ-11048 이동하기 Swift  (0) 2023.06.02
BOJ-14502 연구소 Swift  (0) 2023.06.01
BOJ-2810 컵홀더 Swift  (0) 2023.06.01
BOJ-9655 돌 게임 Swift  (0) 2023.06.01

문제

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다.

연구소는 크기가 N×M인 직사각형으로 나타낼 수 있으며, 직사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다. 

일부 칸은 바이러스가 존재하며, 이 바이러스는 상하좌우로 인접한 빈 칸으로 모두 퍼져나갈 수 있다. 새로 세울 수 있는 벽의 개수는 3개이며, 꼭 3개를 세워야 한다.

예를 들어, 아래와 같이 연구소가 생긴 경우를 살펴보자.

2 0 0 0 1 1 0
0 0 1 0 1 2 0
0 1 1 0 1 0 0
0 1 0 0 0 0 0
0 0 0 0 0 1 1
0 1 0 0 0 0 0
0 1 0 0 0 0 0

이때, 0은 빈 칸, 1은 벽, 2는 바이러스가 있는 곳이다. 아무런 벽을 세우지 않는다면, 바이러스는 모든 빈 칸으로 퍼져나갈 수 있다.

2행 1열, 1행 2열, 4행 6열에 벽을 세운다면 지도의 모양은 아래와 같아지게 된다.

2 1 0 0 1 1 0
1 0 1 0 1 2 0
0 1 1 0 1 0 0
0 1 0 0 0 1 0
0 0 0 0 0 1 1
0 1 0 0 0 0 0
0 1 0 0 0 0 0

바이러스가 퍼진 뒤의 모습은 아래와 같아진다.

2 1 0 0 1 1 2
1 0 1 0 1 2 2
0 1 1 0 1 2 2
0 1 0 0 0 1 2
0 0 0 0 0 1 1
0 1 0 0 0 0 0
0 1 0 0 0 0 0

벽을 3개 세운 뒤, 바이러스가 퍼질 수 없는 곳을 안전 영역이라고 한다. 위의 지도에서 안전 영역의 크기는 27이다.

연구소의 지도가 주어졌을 때 얻을 수 있는 안전 영역 크기의 최댓값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 지도의 세로 크기 N과 가로 크기 M이 주어진다. (3 ≤ N, M ≤ 8)

둘째 줄부터 N개의 줄에 지도의 모양이 주어진다. 0은 빈 칸, 1은 벽, 2는 바이러스가 있는 위치이다. 2의 개수는 2보다 크거나 같고, 10보다 작거나 같은 자연수이다.

빈 칸의 개수는 3개 이상이다.

출력

첫째 줄에 얻을 수 있는 안전 영역의 최대 크기를 출력한다.

내가 푼 풀이

- 해당문제는 완전탐색으로 모든 벽을 세우는 경우의 수를 조사하고, 바이러스를 퍼트린다.

- 바이러스를 퍼트렸을때, 남아있는 안전한구역이 최대가되는값을 출력한다.

- 3개의 벽을 세우는 모든 경우의 수를 만드는 방법 DFS

- 벽을 만든 후 상하좌우 인접한 지점에 바이러스를 퍼트리는 과정 BFS

 

 

import Foundation

var input = readLine()!.split(separator: " ").map{ Int($0)! }
var arr = [[Int]]()
var startIdx = [[Int]]()
let dx = [1,0,-1,0]
let dy = [0,1,0,-1]
var max = Int.min

// 주어진 연구소의 구조를 배열로 입력
// 바이러스 시작지점 저장
for i in 0..<input[0] {
    var a = readLine()!.split(separator: " ").map{ Int($0)! }
    arr.append(a)
    for j in 0..<arr[i].count {
        if arr[i][j] == 2 {
            startIdx.append([i,j])
        }
    }
}

// DFS
// 벽을 총 3개 세우는 모든 경우의 수
// 벽 3개를 세웠다면 바이러스를 퍼뜨림(BFS)
func walls(_ num: Int) {
    if num == 3 {
        bfs()
        return
    }
    for i in 0..<input[0] {
        for j in 0..<input[1] {
            if arr[i][j] == 0 {
                arr[i][j] = 1
                walls(num+1)
                arr[i][j] = 0
            }
        }
    }
}

// BFS
// 벽이 세워졌다면 바이러스를 퍼뜨린다.
// 모든 바이러스가 퍼진 후 안전구역의 수를 센다.
// 안전구역 최대값 최신화
func bfs() {
    var cp = [[Int]]()
    for i in 0..<input[0] {
        cp.append(arr[i])
    }
    
    var needVisitQueue = startIdx
    var idx = 0

    while !needVisitQueue.isEmpty {
        var node = needVisitQueue.removeFirst()
        
        for j in 0..<4 {
            var x = node[0] + dx[j]
            var y = node[1] + dy[j]

            if (x >= 0 && x < input[0]) && (y >= 0 && y < input[1]) && cp[x][y] == 0 {
                cp[x][y] = 2
                needVisitQueue.append([x,y])
            }
        }
    }
    
    var c = 0
    for i in 0..<cp.count {
        for j in 0..<cp[0].count {
            if cp[i][j] == 0 {
                c += 1
            }
        }
    }
    if max < c {
        max = c
    }
}

walls(0)
print(max)

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-11048 이동하기 Swift  (0) 2023.06.02
BOJ-1753 최단경로 Swift  (0) 2023.06.01
BOJ-2810 컵홀더 Swift  (0) 2023.06.01
BOJ-9655 돌 게임 Swift  (0) 2023.06.01
BOJ-9184 신나는 함수 실행 Swift  (0) 2023.06.01

문제

십년이면 강산이 변한다.

강산이네 동네에 드디어 극장이 생겼고, 강산이는 극장에 놀러갔다. 매점에서 콜라를 산 뒤, 자리에 앉은 강산이는 큰 혼란에 빠졌다. 양쪽 컵홀더를 이미 옆 사람들이 차지했기 때문에 콜라를 꽂을 컵 홀더가 없었기 때문이다. 영화를 보는 내내 콜라를 손에 들고 있던 강산이는 극장에 다시 왔을 때는 꼭 콜라를 컵 홀더에 놓겠다는 다짐을 한 후 집에 돌아갔다.

극장의 한 줄에는 자리가 N개가 있다. 서로 인접한 좌석 사이에는 컵홀더가 하나씩 있고, 양 끝 좌석에는 컵홀더가 하나씩 더 있다. 또, 이 극장에는 커플석이 있다. 커플석 사이에는 컵홀더가 없다.

극장의 한 줄의 정보가 주어진다. 이때, 이 줄에 사람들이 모두 앉았을 때, 컵홀더에 컵을 꽂을 수 있는 최대 사람의 수를 구하는 프로그램을 작성하시오. 모든 사람은 컵을 한 개만 들고 있고, 자신의 좌석의 양 옆에 있는 컵홀더에만 컵을 꽂을 수 있다.

S는 일반 좌석, L은 커플석을 의미하며, L은 항상 두개씩 쌍으로 주어진다.

어떤 좌석의 배치가 SLLLLSSLL일때, 컵홀더를 *로 표시하면 아래와 같다.

*S*LL*LL*S*S*LL*

위의 예에서 적어도 두 명은 컵홀더를 사용할 수 없다.

입력

첫째 줄에 좌석의 수 N이 주어진다. (1 ≤ N ≤ 50) 둘째 줄에는 좌석의 정보가 주어진다.

출력

컵을 컵홀더에 놓을 수 있는 최대 사람의 수를 출력한다.

내가 푼 풀이

- 주어진 문자열을 일반석이면 주변에 양쪽에 *하나를, 커플석이면 두 개의 쌍 양쪽으로 *을 넣어준다

- 좌석과 상관없이 양 끝 좌석에 컵홀더 하나씩 있으므로, 오른쪽이든 왼쪽이든 한쪽을 기준으로 컵홀더를 모두 써가면 최대로 이용할 수 있다.

- 컵홀더까지 포함된 배열에서 두개씩 추출하여 좌석과 컵홀더를 포함하면 카운트해 주고, 커플석처럼 컵홀더를 포함하지 않으면 한자리를 넘겨서 세준다.

 

해당 조건을 토대로 코드로 구현한다.

 

import Foundation

let count = Int(readLine()!)!
var sit = Array(readLine()!).map{ String($0)}
var set = ["*"]
var idx = 0
var result = 0

// 주어진 문자열을 컵홀더위치까지 넣어준다.
while idx < sit.count {
    if sit[idx] == "S" {
        set.append(sit[idx])
        set.append("*")
        idx += 1
    } else {
        set.append(sit[idx])
        set.append(sit[idx+1])
        set.append("*")
        idx += 2
    }
}
idx = 0

// 컵홀더까지 포함된 문자열에서 두개씩 쌍으로 추출하여 좌석과 컵홀더로 존재하면 카운트
// 커플석과같이 L L 이 추출되면 한칸 건너뛰어서 재추출한다.
while idx < set.count - 1 {
    var s1 = set[idx]
    var s2 = set[idx+1]
    if s1 == "*" || s2 == "*" {
        result += 1
        idx += 2
    } else {
        idx += 1
    }
}

print(result)

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-1753 최단경로 Swift  (0) 2023.06.01
BOJ-14502 연구소 Swift  (0) 2023.06.01
BOJ-9655 돌 게임 Swift  (0) 2023.06.01
BOJ-9184 신나는 함수 실행 Swift  (0) 2023.06.01
BOJ-11724 연결 요소의 개수 Swift  (0) 2023.05.31

문제

돌 게임은 두 명이서 즐기는 재밌는 게임이다.

탁자 위에 돌 N개가 있다. 상근이와 창영이는 턴을 번갈아가면서 돌을 가져가며, 돌은 1개 또는 3개 가져갈 수 있다. 마지막 돌을 가져가는 사람이 게임을 이기게 된다.

두 사람이 완벽하게 게임을 했을 때, 이기는 사람을 구하는 프로그램을 작성하시오. 게임은 상근이가 먼저 시작한다.

입력

첫째 줄에 N이 주어진다. (1 ≤ N ≤ 1000)

출력

상근이가 게임을 이기면 SK를, 창영이가 게임을 이기면 CY을 출력한다.

내가 푼 풀이

- 문제를 이해하기 어려웠는데,, 마지막 돌을 가져간사람이 이기게된다.

- 돌이 2개남았을때, 3개를 가져가서 마지막돌을 가져가는것이 아니라, 3개미만으로 남았을땐 1개씩밖에 못가져간다.

- 이렇게 마지막돌을 가져간 사람이 우승하는것이다.

- 돌이 1개있다면, 상근이가 먼저시작하므로 상근이가 1개 가져가면 이기게된다.

- 돌이 2개있다면, 상근이가 1개 가져가고, 창영이가 마지막돌 1개를 가져가므로 창영이가 이기게된다.

- 돌이 3개가 있다면, 상근이가 먼저 3개를 가져가면 마지막돌을 가져가므로 상근이가 이기게된다.

- 이를 점화식으로 만들어보자.

- dp[n] = n개의 돌이 있을때, 진행되는 순서 로 정의하자.

- dp[1] = 1, dp[2] : 총 두차례가 진행되므로 dp[2] = 2, dp[3]: 3개 가져가므로 한차례에 게임이 끝난다 dp[3] = 1

- n % 3 == 0 이라면 dp[n] = n / 3

- n % 3 != 0 이라면 dp[n] = dp[i / 3] + dp[i % 3] 이 된다.

 

이렇게 진행된 순서의 수가 홀수라면, 마지막돌을 가져간 사람은 상근이고, 짝수라면 창영이다.

 

import Foundation

var num = Int(readLine()!)!

var dp = Array(repeating: 0, count: 1001)
dp[1] = 1
dp[2] = 2
dp[3] = 1

// dp
for i in 1...1000 {
    if i % 3 == 0 {
        dp[i] = i / 3
    } else {
        dp[i] = dp[i/3] + dp[i%3]
    }
}

if dp[num] % 2 != 0 {
    print("SK")
} else {
    print("CY")
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-14502 연구소 Swift  (0) 2023.06.01
BOJ-2810 컵홀더 Swift  (0) 2023.06.01
BOJ-9184 신나는 함수 실행 Swift  (0) 2023.06.01
BOJ-11724 연결 요소의 개수 Swift  (0) 2023.05.31
BOJ-12904 A와B Swift  (0) 2023.05.31

문제

재귀 호출만 생각하면 신이 난다! 아닌가요?

다음과 같은 재귀함수 w(a, b, c)가 있다.

if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns:
    1

if a > 20 or b > 20 or c > 20, then w(a, b, c) returns:
    w(20, 20, 20)

if a < b and b < c, then w(a, b, c) returns:
    w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)

otherwise it returns:
    w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)

위의 함수를 구현하는 것은 매우 쉽다. 하지만, 그대로 구현하면 값을 구하는데 매우 오랜 시간이 걸린다. (예를 들면, a=15, b=15, c=15)

a, b, c가 주어졌을 때, w(a, b, c)를 출력하는 프로그램을 작성하시오.

입력

입력은 세 정수 a, b, c로 이루어져 있으며, 한 줄에 하나씩 주어진다. 입력의 마지막은 -1 -1 -1로 나타내며, 세 정수가 모두 -1인 경우는 입력의 마지막을 제외하면 없다.

출력

입력으로 주어진 각각의 a, b, c에 대해서, w(a, b, c)를 출력한다.

내가 푼 풀이

- 주어진 함수를 재귀로 돌리면 시간이 너무 오래 걸리므로 저장된 값을 재사용하는 메모리이제이션 을 이용한다.

- dp[a][b][c] = w(a,b,c)의 값이라 하고, 해당 조건에 맞게 dp값에 저장하고 재사용한다.

 

 

import Foundation

var dp = Array(repeating: Array(repeating: Array(repeating: -1, count: 21), count: 21), count: 21)

func w(_ a: Int,_ b: Int,_ c: Int) -> Int {
    if a <= 0 || b <= 0 || c <= 0 {
        return 1
    }
    if a > 20 || b > 20 || c > 20 {
        return w(20, 20, 20)
    }
    if dp[a][b][c] != -1 {
        return dp[a][b][c]
    }
    if a < b && b < c {
        dp[a][b][c] = w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)
        return dp[a][b][c]
    } else {
        dp[a][b][c] = w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)
        return dp[a][b][c]
    }
}


while true {
    var input = readLine()!.split(separator: " ").map{ Int($0)! }
    
    if input[0] == -1 && input[1] == -1 && input[2] == -1 {
        break
    }
    print("w(\(input[0]), \(input[1]), \(input[2])) = \(w(input[0], input[1], input[2]))")
}

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-2810 컵홀더 Swift  (0) 2023.06.01
BOJ-9655 돌 게임 Swift  (0) 2023.06.01
BOJ-11724 연결 요소의 개수 Swift  (0) 2023.05.31
BOJ-12904 A와B Swift  (0) 2023.05.31
BOJ-2225 합분해 Swift  (0) 2023.05.31

+ Recent posts