Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions youngjoo00/week_14/BOJ_11404_플로이드.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// BOJ_11404_플로이드.swift

let city = Int(readLine()!)!
let bus = Int(readLine()!)!
let INF = Int.max
var graph: [[Int]] = Array(repeating: Array(repeating: INF, count: city + 1), count: city + 1)

// 본인은 가중치 0
for i in 1...city {
graph[i][i] = 0
}

for _ in 0..<bus {
let input = readLine()!.split(separator: " ").map { Int($0)! }
// 시작 도시와 도착 도시를 연결하는 노선이 1개가 아닐 수 있기 때문에, 비용이 가장 작은 비용으로 저장해야 함
graph[input[0]][input[1]] = min(graph[input[0]][input[1]], input[2])
}

floydWarshall(graph: &graph)

func floydWarshall(graph: inout [[Int]]) {
// 모든 정점 쌍에 대해 1...n 까지 순회
let n = city + 1

for k in 1..<n { // 첫 번째 반복문은 거쳐가는 노드를 선택하는 k를 반복한다.
for i in 1..<n { // 두 번째 반복문은 출발 노드를 선택하는 i를 순회한다.
for j in 1..<n { // 세 번째 반복문은 도착 노드를 선택하는 j를 순회한다.
// 실제 경로가 존재하지 않으면 해당 덧셈 연산을 수행하지 않고 오버플로우를 방지
if graph[i][k] < Int.max && graph[k][j] < Int.max {
// 더 짧은 경로를 찾으면 업데이트
graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])
}
}
}
}
}

for y in 1...city {
for x in 1...city {
print(graph[y][x] == INF ? 0 : graph[y][x], terminator: " ")
}
print()
}
50 changes: 50 additions & 0 deletions youngjoo00/week_15/BOJ_12852_1로 만들기 2.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// BOJ_12852_1로 만들기 2.swift

var n = Int(readLine()!)!

if n == 1 {
print(0)
print(1)
} else {
// dp[i] 는 n 을 1로 만드는데 필요한 계산 횟수를 담아둠
var dp: [Int] = Array(repeating: Int.max, count: n + 1)
var path: [Int] = Array(repeating: 0, count: n + 1)

dp[1] = 0

for i in 2...n {
// i 를 1로 만들기 위해 필요한 최소 계산 횟수
dp[i] = dp[i-1] + 1

// 현재 계산하고 있는 인덱스를 기억하는 배열
path[i] = i - 1

// 현재 인덱스의 횟수 vs. 인덱스를 2로 나누고 + 1(나누는 데 사용한 횟수)
// 이 둘을 비교해서 적은 횟수를 dp[i] 에 담음
if i % 2 == 0 && dp[i] > dp[i/2] + 1 {
dp[i] = dp[i/2] + 1
path[i] = i / 2
}

// 현재 인덱스의 횟수 vs. 인덱스를 3로 나누고 + 1(나누는 데 사용한 횟수)
// 이 둘을 비교해서 적은 횟수를 dp[i] 에 담음
if i % 3 == 0 && dp[i] > dp[i/3] + 1 {
dp[i] = dp[i/3] + 1
path[i] = i / 3
}
}

print(dp[n])

var list: [Int] = []

// 인덱스를 갖고 역추적하기
var current = n

while current != 0 {
list.append(current)
current = path[current]
}

list.forEach { print($0, terminator: " ") }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// BOJ_14002_가장 긴 증가하는 부분 수열 4.swift

let n = Int(readLine()!)!
let array = readLine()!.split(separator: " ").map { Int($0)! }
var dp = Array(repeating: 1, count: n)

for i in 0..<n {
for j in 0..<i {
// 실제 값이 어떤 것이 더 큰지 비교
if array[i] > array[j] {
// dp 배열에 있는 값중 현재 순회하는 dp[i] 와 직전의 담아둔 값 + 1 중에 어떤 것이 더 큰지 비교
if dp[i] < dp[j] + 1 {
dp[i] = dp[j] + 1
}
}
}
}

var LIS: [Int] = []
var length = dp.max()!
print(length)

// 역순으로 순회
for i in (0..<n).reversed() {
// 연속적으로 이루어진 수열이기에 큰 값부터 확인해서 역순으로 넣음
if dp[i] == length {
LIS.append(array[i])
length -= 1
}
}

// 내림차순 되어있는 값을 오름차순으로 변경해서 출력
print(LIS.reversed().map { String($0) }.joined(separator: " "))
54 changes: 54 additions & 0 deletions youngjoo00/week_15/BOJ_9252_LCS 2.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// BOJ_9252_LCS 2.swift

let input1 = readLine()!.map { $0 }
let input2 = readLine()!.map { $0 }

var dp = Array(repeating: Array(repeating: 0, count: input2.count + 1), count: input1.count + 1)

// input1과 input2의 각 문자를 순회하며 dp 테이블 업데이트
// 두 문자가 같다면 이전단계 까지의 최장 공통 수열이 가진 값 + 1 을 진행
for i in 1...input1.count {
for j in 1...input2.count {
// 현재 문자가 같은 경우, 왼쪽 위 대각선 값에 1을 더해 현재 위치에 저장
if input1[i-1] == input2[j-1] {
dp[i][j] = dp[i-1][j-1] + 1
} else {
// 현재 문자가 다른 경우, 왼쪽 값과 위쪽 값 중 더 큰 값을 현재 위치에 저장
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
}
}
}

// dp 테이블의 마지막 요소 출력: input1과 input2의 최장 공통 부분 수열(LCS)의 길이
print(dp[input1.count][input2.count])

// LCS를 추출하기 위한 결과 배열
var result: [Character] = []

// dp 테이블의 오른쪽 아래에서 시작
var i = input1.count
var j = input2.count

// 역추적 시작
while i > 0 && j > 0 {
// 위쪽으로 이동: 현재 위치의 값이 위쪽 값과 같은 경우
if dp[i][j] == dp[i-1][j] {
i -= 1
} else if dp[i][j] == dp[i][j-1] { // 왼쪽으로 이동: 현재 위치의 값이 왼쪽 값과 같은 경우
j -= 1
} else {
// 대각선으로 이동: 현재 위치의 값이 왼쪽 위 대각선 값 + 1인 경우.
// 해당 문자가 LCS에 포함되므로 결과 배열에 추가
result.append(input1[i-1])
i -= 1
j -= 1
}
}

// 결과 배열을 뒤집어서 올바른 순서로 만듬
let reversedResult = result.reversed()

// 결과 배열이 비어있지 않다면, 결과 배열의 각 문자를 출력함
if !reversedResult.isEmpty {
reversedResult.forEach { print($0, terminator: "") }
}