diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..ae51306
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+*.py linguist-detectable=true
+*.cpp linguist-detectable=false
+*.java linguist-detectable=false
diff --git a/1/1.py b/1/1.py
new file mode 100644
index 0000000..77377a9
--- /dev/null
+++ b/1/1.py
@@ -0,0 +1,6 @@
+import time
+start_time = time.time() # 측정 시작
+
+# 프로그램 소스코드
+end_time = time.time() # 측정 종료
+print("time:", end_time - start_time) # 수행 시간 출력
diff --git a/1/2.py b/1/2.py
new file mode 100644
index 0000000..b744beb
--- /dev/null
+++ b/1/2.py
@@ -0,0 +1,35 @@
+from random import randint
+import time
+
+# 배열에 10,000개의 정수를 삽입
+array = []
+for _ in range(10000):
+    array.append(randint(1, 100)) # 1부터 100 사이의 랜덤한 정수
+
+# 선택 정렬 프로그램 성능 측정
+start_time = time.time()
+
+# 선택 정렬 프로그램 소스코드
+for i in range(len(array)):
+    min_index = i # 가장 작은 원소의 인덱스
+    for j in range(i + 1, len(array)):
+        if array[min_index] > array[j]:
+            min_index = j
+    array[i], array[min_index] = array[min_index], array[i] # 스와프
+
+end_time = time.time() # 측정 종료
+print("선택 정렬 성능 측정:", end_time - start_time) # 수행 시간 출력
+
+# 배열을 다시 무작위 데이터로 초기화
+array = []
+for _ in range(10000):
+    array.append(randint(1, 100)) # 1부터 100 사이의 랜덤한 정수
+
+# 기본 정렬 라이브러리 성능 측정
+start_time = time.time()
+
+# 기본 정렬 라이브러리 사용
+array.sort()
+
+end_time = time.time() # 측정 종료
+print("기본 정렬 라이브러리 성능 측정:", end_time - start_time) # 수행 시간 출력
diff --git a/10/1.cpp b/10/1.cpp
new file mode 100644
index 0000000..4ad2f17
--- /dev/null
+++ b/10/1.cpp
@@ -0,0 +1,53 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수(V)와 간선(Union 연산)의 개수(E)
+// 노드의 개수는 최대 100,000개라고 가정
+int v, e;
+int parent[100001]; // 부모 테이블 초기화하기
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> v >> e;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= v; i++) {
+        parent[i] = i;
+    }
+
+    // Union 연산을 각각 수행
+    for (int i = 0; i < e; i++) {
+        int a, b;
+        cin >> a >> b;
+        unionParent(a, b);
+    }
+
+    // 각 원소가 속한 집합 출력하기
+    cout << "각 원소가 속한 집합: ";
+    for (int i = 1; i <= v; i++) {
+        cout << findParent(i) << ' ';
+    }
+    cout << '\n';
+
+    // 부모 테이블 내용 출력하기
+    cout << "부모 테이블: ";
+    for (int i = 1; i <= v; i++) {
+        cout << parent[i] << ' ';
+    }
+    cout << '\n';
+}
\ No newline at end of file
diff --git a/10/1.java b/10/1.java
new file mode 100644
index 0000000..ee96575
--- /dev/null
+++ b/10/1.java
@@ -0,0 +1,57 @@
+import java.util.*;
+
+public class Main {
+
+    // 노드의 개수(V)와 간선(Union 연산)의 개수(E)
+    // 노드의 개수는 최대 100,000개라고 가정
+    public static int v, e;
+    public static int[] parent = new int[100001]; // 부모 테이블 초기화하기
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        v = sc.nextInt();
+        e = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= v; i++) {
+            parent[i] = i;
+        }
+
+        // Union 연산을 각각 수행
+        for (int i = 0; i < e; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            unionParent(a, b);
+        }
+
+        // 각 원소가 속한 집합 출력하기
+        System.out.print("각 원소가 속한 집합: ");
+        for (int i = 1; i <= v; i++) {
+            System.out.print(findParent(i) + " ");
+        }
+        System.out.println();
+
+        // 부모 테이블 내용 출력하기
+        System.out.print("부모 테이블: ");
+        for (int i = 1; i <= v; i++) {
+            System.out.print(parent[i] + " ");
+        }
+        System.out.println();
+    }
+}
\ No newline at end of file
diff --git a/10/2.py b/10/2.py
index d074ff6..a32e24e 100644
--- a/10/2.py
+++ b/10/2.py
@@ -1,40 +1,4 @@
-# 특정 원소가 속한 집합을 찾기
 def find_parent(parent, x):
-    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
     if parent[x] != x:
         parent[x] = find_parent(parent, parent[x])
-    return parent[x]
-
-# 두 원소가 속한 집합을 합치기
-def union_parent(parent, a, b):
-    a = find_parent(parent, a)
-    b = find_parent(parent, b)
-    if a < b:
-        parent[b] = a
-    else:
-        parent[a] = b
-
-# 노드의 개수와 간선(Union 연산)의 개수 입력 받기
-v, e = map(int, input().split())
-parent = [0] * (v + 1) # 부모 테이블 초기화하기
-
-# 부모 테이블상에서, 부모를 자기 자신으로 초기화
-for i in range(1, v + 1):
-    parent[i] = i
-
-# Union 연산을 각각 수행
-for i in range(e):
-    a, b = map(int, input().split())
-    union_parent(parent, a, b)
-
-# 각 원소가 속한 집합 출력하기
-print('각 원소가 속한 집합: ', end='')
-for i in range(1, v + 1):
-    print(find_parent(parent, i), end=' ')
-
-print()
-
-# 부모 테이블 내용 출력하기
-print('부모 테이블: ', end='')
-for i in range(1, v + 1):
-    print(parent[i], end=' ')
+    return parent[x]
\ No newline at end of file
diff --git a/10/3.cpp b/10/3.cpp
new file mode 100644
index 0000000..eed364c
--- /dev/null
+++ b/10/3.cpp
@@ -0,0 +1,53 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수(V)와 간선(Union 연산)의 개수(E)
+// 노드의 개수는 최대 100,000개라고 가정
+int v, e;
+int parent[100001]; // 부모 테이블 초기화
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return parent[x] = findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> v >> e;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= v; i++) {
+        parent[i] = i;
+    }
+
+    // Union 연산을 각각 수행
+    for (int i = 0; i < e; i++) {
+        int a, b;
+        cin >> a >> b;
+        unionParent(a, b);
+    }
+
+    // 각 원소가 속한 집합 출력하기
+    cout << "각 원소가 속한 집합: ";
+    for (int i = 1; i <= v; i++) {
+        cout << findParent(i) << ' ';
+    }
+    cout << '\n';
+
+    // 부모 테이블 내용 출력하기
+    cout << "부모 테이블: ";
+    for (int i = 1; i <= v; i++) {
+        cout << parent[i] << ' ';
+    }
+    cout << '\n';
+}
diff --git a/10/3.java b/10/3.java
new file mode 100644
index 0000000..7be5d71
--- /dev/null
+++ b/10/3.java
@@ -0,0 +1,57 @@
+import java.util.*;
+
+public class Main {
+
+    // 노드의 개수(V)와 간선(Union 연산)의 개수(E)
+    // 노드의 개수는 최대 100,000개라고 가정
+    public static int v, e;
+    public static int[] parent = new int[100001]; // 부모 테이블 초기화하기
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return parent[x] = findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        v = sc.nextInt();
+        e = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= v; i++) {
+            parent[i] = i;
+        }
+
+        // Union 연산을 각각 수행
+        for (int i = 0; i < e; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            unionParent(a, b);
+        }
+
+        // 각 원소가 속한 집합 출력하기
+        System.out.print("각 원소가 속한 집합: ");
+        for (int i = 1; i <= v; i++) {
+            System.out.print(findParent(i) + " ");
+        }
+        System.out.println();
+
+        // 부모 테이블 내용 출력하기
+        System.out.print("부모 테이블: ");
+        for (int i = 1; i <= v; i++) {
+            System.out.print(parent[i] + " ");
+        }
+        System.out.println();
+    }
+}
\ No newline at end of file
diff --git a/10/3.py b/10/3.py
index 5075534..d074ff6 100644
--- a/10/3.py
+++ b/10/3.py
@@ -22,19 +22,19 @@ def union_parent(parent, a, b):
 for i in range(1, v + 1):
     parent[i] = i
 
-cycle = False # 사이클 발생 여부
-
+# Union 연산을 각각 수행
 for i in range(e):
     a, b = map(int, input().split())
-    # 사이클이 발생한 경우 종료
-    if find_parent(parent, a) == find_parent(parent, b):
-        cycle = True
-        break
-    # 사이클이 발생하지 않았다면 합치기(Union) 수행
-    else:
-        union_parent(parent, a, b)
+    union_parent(parent, a, b)
+
+# 각 원소가 속한 집합 출력하기
+print('각 원소가 속한 집합: ', end='')
+for i in range(1, v + 1):
+    print(find_parent(parent, i), end=' ')
+
+print()
 
-if cycle:
-    print("사이클이 발생했습니다.")
-else:
-    print("사이클이 발생하지 않았습니다.")
+# 부모 테이블 내용 출력하기
+print('부모 테이블: ', end='')
+for i in range(1, v + 1):
+    print(parent[i], end=' ')
diff --git a/10/4.cpp b/10/4.cpp
new file mode 100644
index 0000000..fd50637
--- /dev/null
+++ b/10/4.cpp
@@ -0,0 +1,55 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수(V)와 간선(Union 연산)의 개수(E)
+// 노드의 개수는 최대 100,000개라고 가정
+int v, e;
+int parent[100001]; // 부모 테이블 초기화
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return parent[x] = findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> v >> e;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= v; i++) {
+        parent[i] = i;
+    }
+
+    bool cycle = false; // 사이클 발생 여부
+
+    for (int i = 0; i < e; i++) {
+        int a, b;
+        cin >> a >> b;
+        // 사이클이 발생한 경우 종료
+        if (findParent(a) == findParent(b)) {
+            cycle = true;
+            break;
+        }
+        // 사이클이 발생하지 않았다면 합집합(Union) 연산 수행
+        else {
+            unionParent(a, b);
+        }
+    }
+
+    if (cycle) {
+        cout << "사이클이 발생했습니다." << '\n';
+    }
+    else {
+        cout << "사이클이 발생하지 않았습니다." << '\n';
+    }
+}
diff --git a/10/4.java b/10/4.java
new file mode 100644
index 0000000..2cb6c6b
--- /dev/null
+++ b/10/4.java
@@ -0,0 +1,59 @@
+import java.util.*;
+
+public class Main {
+
+    // 노드의 개수(V)와 간선(Union 연산)의 개수(E)
+    // 노드의 개수는 최대 100,000개라고 가정
+    public static int v, e;
+    public static int[] parent = new int[100001]; // 부모 테이블 초기화하기
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return parent[x] = findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        v = sc.nextInt();
+        e = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= v; i++) {
+            parent[i] = i;
+        }
+
+        boolean cycle = false; // 사이클 발생 여부
+
+        for (int i = 0; i < e; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            // 사이클이 발생한 경우 종료
+            if (findParent(a) == findParent(b)) {
+                cycle = true;
+                break;
+            }
+            // 사이클이 발생하지 않았다면 합집합(Union) 연산 수행
+            else {
+                unionParent(a, b);
+            }
+        }
+
+        if (cycle) {
+            System.out.println("사이클이 발생했습니다.");
+        }
+        else {
+            System.out.println("사이클이 발생하지 않았습니다.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/10/4.py b/10/4.py
index 5eaa1e8..29a59ed 100644
--- a/10/4.py
+++ b/10/4.py
@@ -18,29 +18,23 @@ def union_parent(parent, a, b):
 v, e = map(int, input().split())
 parent = [0] * (v + 1) # 부모 테이블 초기화하기
 
-# 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
-edges = []
-result = 0
-
 # 부모 테이블상에서, 부모를 자기 자신으로 초기화
 for i in range(1, v + 1):
     parent[i] = i
 
-# 모든 간선에 대한 정보를 입력 받기
-for _ in range(e):
-    a, b, cost = map(int, input().split())
-    # 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
-    edges.append((cost, a, b))
-
-# 간선을 비용순으로 정렬
-edges.sort()
+cycle = False # 사이클 발생 여부
 
-# 간선을 하나씩 확인하며
-for edge in edges:
-    cost, a, b = edge
-    # 사이클이 발생하지 않는 경우에만 집합에 포함
-    if find_parent(parent, a) != find_parent(parent, b):
+for i in range(e):
+    a, b = map(int, input().split())
+    # 사이클이 발생한 경우 종료
+    if find_parent(parent, a) == find_parent(parent, b):
+        cycle = True
+        break
+    # 사이클이 발생하지 않았다면 합집합(Union) 연산 수행
+    else:
         union_parent(parent, a, b)
-        result += cost
 
-print(result)
+if cycle:
+    print("사이클이 발생했습니다.")
+else:
+    print("사이클이 발생하지 않았습니다.")
diff --git a/10/5.cpp b/10/5.cpp
new file mode 100644
index 0000000..c668462
--- /dev/null
+++ b/10/5.cpp
@@ -0,0 +1,60 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수(V)와 간선(Union 연산)의 개수(E)
+// 노드의 개수는 최대 100,000개라고 가정
+int v, e;
+int parent[100001]; // 부모 테이블 초기화
+// 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+vector<pair<int, pair<int, int> > > edges;
+int result = 0;
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return parent[x] = findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> v >> e;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= v; i++) {
+        parent[i] = i;
+    }
+
+    // 모든 간선에 대한 정보를 입력 받기
+    for (int i = 0; i < e; i++) {
+        int a, b, cost;
+        cin >> a >> b >> cost;
+        // 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
+        edges.push_back({cost, {a, b}});
+    }
+
+    // 간선을 비용순으로 정렬
+    sort(edges.begin(), edges.end());
+
+    // 간선을 하나씩 확인하며
+    for (int i = 0; i < edges.size(); i++) {
+        int cost = edges[i].first;
+        int a = edges[i].second.first;
+        int b = edges[i].second.second;
+        // 사이클이 발생하지 않는 경우에만 집합에 포함
+        if (findParent(a) != findParent(b)) {
+            unionParent(a, b);
+            result += cost;
+        }
+    }
+
+    cout << result << '\n';
+}
diff --git a/10/5.java b/10/5.java
new file mode 100644
index 0000000..0404ba4
--- /dev/null
+++ b/10/5.java
@@ -0,0 +1,98 @@
+import java.util.*;
+
+class Edge implements Comparable<Edge> {
+
+    private int distance;
+    private int nodeA;
+    private int nodeB;
+
+    public Edge(int distance, int nodeA, int nodeB) {
+        this.distance = distance;
+        this.nodeA = nodeA;
+        this.nodeB = nodeB;
+    }
+
+    public int getDistance() {
+        return this.distance;
+    }
+
+    public int getNodeA() {
+        return this.nodeA;
+    }
+
+    public int getNodeB() {
+        return this.nodeB;
+    }
+
+    // 거리(비용)가 짧은 것이 높은 우선순위를 가지도록 설정
+    @Override
+    public int compareTo(Edge other) {
+        if (this.distance < other.distance) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+
+    // 노드의 개수(V)와 간선(Union 연산)의 개수(E)
+    // 노드의 개수는 최대 100,000개라고 가정
+    public static int v, e;
+    public static int[] parent = new int[100001]; // 부모 테이블 초기화하기
+    // 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+    public static ArrayList<Edge> edges = new ArrayList<>();
+    public static int result = 0;
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return parent[x] = findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        v = sc.nextInt();
+        e = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= v; i++) {
+            parent[i] = i;
+        }
+
+        // 모든 간선에 대한 정보를 입력 받기
+        for (int i = 0; i < e; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            int cost = sc.nextInt();
+            edges.add(new Edge(cost, a, b));
+        }
+
+        // 간선을 비용순으로 정렬
+        Collections.sort(edges);
+
+        // 간선을 하나씩 확인하며
+        for (int i = 0; i < edges.size(); i++) {
+            int cost = edges.get(i).getDistance();
+            int a = edges.get(i).getNodeA();
+            int b = edges.get(i).getNodeB();
+            // 사이클이 발생하지 않는 경우에만 집합에 포함
+            if (findParent(a) != findParent(b)) {
+                unionParent(a, b);
+                result += cost;
+            }
+        }
+
+        System.out.println(result);
+    }
+}
diff --git a/10/5.py b/10/5.py
index 12fc9ba..5eaa1e8 100644
--- a/10/5.py
+++ b/10/5.py
@@ -1,42 +1,46 @@
-from collections import deque
+# 특정 원소가 속한 집합을 찾기
+def find_parent(parent, x):
+    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if parent[x] != x:
+        parent[x] = find_parent(parent, parent[x])
+    return parent[x]
 
-# 노드의 개수와 간선의 개수를 입력 받기
+# 두 원소가 속한 집합을 합치기
+def union_parent(parent, a, b):
+    a = find_parent(parent, a)
+    b = find_parent(parent, b)
+    if a < b:
+        parent[b] = a
+    else:
+        parent[a] = b
+
+# 노드의 개수와 간선(Union 연산)의 개수 입력 받기
 v, e = map(int, input().split())
-# 모든 노드에 대한 진입차수는 0으로 초기화
-indegree = [0] * (v + 1)
-# 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
-adj = [[] for i in range(v + 1)]
+parent = [0] * (v + 1) # 부모 테이블 초기화하기
+
+# 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+edges = []
+result = 0
+
+# 부모 테이블상에서, 부모를 자기 자신으로 초기화
+for i in range(1, v + 1):
+    parent[i] = i
 
-# 방향 그래프의 모든 간선 정보를 입력 받기
+# 모든 간선에 대한 정보를 입력 받기
 for _ in range(e):
-   a, b = map(int, input().split())
-   adj[a].append(b)
-   # 진입 차수를 1 증가
-   indegree[b] += 1
-
-# 위상 정렬 함수
-def topology_sort():
-   result = [] # 알고리즘 수행 결과를 담을 리스트
-   q = deque() # 큐 기능을 위한 deque 라이브러리 사용
-   # 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
-   for i in range(1, v + 1):
-       if indegree[i] == 0:
-           q.append(i)
-
-   # 큐가 빌 때까지 반복
-   while q:
-       # 큐에서 원소 꺼내기
-       now = q.popleft()
-       result.append(now)
-       # 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
-       for i in adj[now]:
-           indegree[i] -= 1
-           # 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
-           if indegree[i] == 0:
-               q.append(i)
-
-   # 위상 정렬을 수행한 결과 출력
-   for i in result:
-       print(i, end=' ')
-
-topology_sort()
+    a, b, cost = map(int, input().split())
+    # 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
+    edges.append((cost, a, b))
+
+# 간선을 비용순으로 정렬
+edges.sort()
+
+# 간선을 하나씩 확인하며
+for edge in edges:
+    cost, a, b = edge
+    # 사이클이 발생하지 않는 경우에만 집합에 포함
+    if find_parent(parent, a) != find_parent(parent, b):
+        union_parent(parent, a, b)
+        result += cost
+
+print(result)
diff --git a/10/6.cpp b/10/6.cpp
new file mode 100644
index 0000000..a5c2dbd
--- /dev/null
+++ b/10/6.cpp
@@ -0,0 +1,60 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수(V)와 간선의 개수(E)
+// 노드의 개수는 최대 100,000개라고 가정
+int v, e;
+// 모든 노드에 대한 진입차수는 0으로 초기화
+int indegree[100001];
+// 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
+vector<int> graph[100001];
+
+// 위상 정렬 함수
+void topologySort() {
+    vector<int> result; // 알고리즘 수행 결과를 담을 리스트
+    queue<int> q; // 큐 라이브러리 사용
+
+    // 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
+    for (int i = 1; i <= v; i++) {
+        if (indegree[i] == 0) {
+            q.push(i);
+        }
+    }
+
+    // 큐가 빌 때까지 반복
+    while (!q.empty()) {
+        // 큐에서 원소 꺼내기
+        int now = q.front();
+        q.pop();
+        result.push_back(now);
+        // 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
+        for (int i = 0; i < graph[now].size(); i++) {
+            indegree[graph[now][i]] -= 1;
+            // 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
+            if (indegree[graph[now][i]] == 0) {
+                q.push(graph[now][i]);
+            }
+        }
+    }
+
+    // 위상 정렬을 수행한 결과 출력
+    for (int i = 0; i < result.size(); i++) {
+        cout << result[i] << ' ';
+    }
+}
+
+int main(void) {
+    cin >> v >> e;
+
+    // 방향 그래프의 모든 간선 정보를 입력 받기
+    for (int i = 0; i < e; i++) {
+        int a, b;
+        cin >> a >> b;
+        graph[a].push_back(b); // 정점 A에서 B로 이동 가능
+        // 진입 차수를 1 증가
+        indegree[b] += 1;
+    }
+
+    topologySort();
+}
diff --git a/10/6.java b/10/6.java
new file mode 100644
index 0000000..58fbbfe
--- /dev/null
+++ b/10/6.java
@@ -0,0 +1,68 @@
+import java.util.*;
+
+public class Main {
+
+    // 노드의 개수(V)와 간선의 개수(E)
+    // 노드의 개수는 최대 100,000개라고 가정
+    public static int v, e;
+    // 모든 노드에 대한 진입차수는 0으로 초기화
+    public static int[] indegree = new int[100001];
+    // 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
+    public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
+
+    // 위상 정렬 함수
+    public static void topologySort() {
+        ArrayList<Integer> result = new ArrayList<>(); // 알고리즘 수행 결과를 담을 리스트
+        Queue<Integer> q = new LinkedList<>(); // 큐 라이브러리 사용
+
+        // 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
+        for (int i = 1; i <= v; i++) {
+            if (indegree[i] == 0) {
+                q.offer(i);
+            }
+        }
+
+        // 큐가 빌 때까지 반복
+        while (!q.isEmpty()) {
+            // 큐에서 원소 꺼내기
+            int now = q.poll();
+            result.add(now);
+            // 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
+            for (int i = 0; i < graph.get(now).size(); i++) {
+                indegree[graph.get(now).get(i)] -= 1;
+                // 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
+                if (indegree[graph.get(now).get(i)] == 0) {
+                    q.offer(graph.get(now).get(i));
+                }
+            }
+        }
+
+        // 위상 정렬을 수행한 결과 출력
+        for (int i = 0; i < result.size(); i++) {
+            System.out.print(result.get(i) + " ");
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        v = sc.nextInt();
+        e = sc.nextInt();
+
+        // 그래프 초기화
+        for (int i = 0; i <= v; i++) {
+            graph.add(new ArrayList<Integer>());
+        }
+
+        // 방향 그래프의 모든 간선 정보를 입력 받기
+        for (int i = 0; i < e; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            graph.get(a).add(b); // 정점 A에서 B로 이동 가능
+            // 진입 차수를 1 증가
+            indegree[b] += 1;
+        }
+
+        topologySort();
+    }
+}
\ No newline at end of file
diff --git a/10/6.py b/10/6.py
index ef4791e..b2717b5 100644
--- a/10/6.py
+++ b/10/6.py
@@ -1,35 +1,43 @@
-# 특정 원소가 속한 집합을 찾기
-def find_parent(parent, x):
-    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
-    if parent[x] != x:
-        parent[x] = find_parent(parent, parent[x])
-    return parent[x]
+from collections import deque
 
-# 두 원소가 속한 집합을 합치기
-def union_parent(parent, a, b):
-    a = find_parent(parent, a)
-    b = find_parent(parent, b)
-    if a < b:
-        parent[b] = a
-    else:
-        parent[a] = b
+# 노드의 개수와 간선의 개수를 입력 받기
+v, e = map(int, input().split())
+# 모든 노드에 대한 진입차수는 0으로 초기화
+indegree = [0] * (v + 1)
+# 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
+graph = [[] for i in range(v + 1)]
 
-n, m = map(int, input().split())
-parent = [0] * (n + 1) # 부모 테이블 초기화하기
+# 방향 그래프의 모든 간선 정보를 입력 받기
+for _ in range(e):
+    a, b = map(int, input().split())
+    graph[a].append(b) # 정점 A에서 B로 이동 가능
+    # 진입 차수를 1 증가
+    indegree[b] += 1
 
-# 부모 테이블상에서, 부모를 자기 자신으로 초기화
-for i in range(0, n + 1):
-    parent[i] = i
+# 위상 정렬 함수
+def topology_sort():
+    result = [] # 알고리즘 수행 결과를 담을 리스트
+    q = deque() # 큐 기능을 위한 deque 라이브러리 사용
 
-# 각 연산을 하나씩 확인한다.
-for i in range(m):
-    oper, a, b = map(int, input().split())
-    # 합치기(Union) 연산인 경우
-    if oper == 0:
-        union_parent(parent, a, b)
-    # 찾기(Find) 연산인 경우
-    elif oper == 1:
-        if find_parent(parent, a) == find_parent(parent, b):
-            print('YES')
-        else:
-            print('NO')
+    # 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
+    for i in range(1, v + 1):
+        if indegree[i] == 0:
+            q.append(i)
+
+    # 큐가 빌 때까지 반복
+    while q:
+        # 큐에서 원소 꺼내기
+        now = q.popleft()
+        result.append(now)
+        # 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
+        for i in graph[now]:
+            indegree[i] -= 1
+            # 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
+            if indegree[i] == 0:
+                q.append(i)
+
+    # 위상 정렬을 수행한 결과 출력
+    for i in result:
+        print(i, end=' ')
+
+topology_sort()
diff --git a/10/7.cpp b/10/7.cpp
new file mode 100644
index 0000000..653e01c
--- /dev/null
+++ b/10/7.cpp
@@ -0,0 +1,50 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수(N)와 연산의 개수(M)
+int n, m;
+int parent[100001]; // 부모 테이블 초기화
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return parent[x] = findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> n >> m;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= n; i++) {
+        parent[i] = i;
+    }
+
+    // 각 연산을 하나씩 확인 
+    for (int i = 0; i < m; i++) {
+        int oper, a, b;
+        cin >> oper >> a >> b;
+        // 합집합(Union) 연산인 경우
+        if (oper == 0) {
+            unionParent(a, b);
+        }
+        // 찾기(Find) 연산인 경우
+        else if (oper == 1) {
+            if (findParent(a) == findParent(b)) {
+                cout << "YES" << '\n';
+            }
+            else {
+                cout << "NO" << '\n';
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/10/7.java b/10/7.java
new file mode 100644
index 0000000..6c599df
--- /dev/null
+++ b/10/7.java
@@ -0,0 +1,56 @@
+import java.util.*;
+
+public class Main {
+
+    // 노드의 개수(N)와 연산의 개수(M)
+    // 노드의 개수는 최대 100,000개라고 가정
+    public static int n, m;
+    public static int[] parent = new int[100001]; // 부모 테이블 초기화
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return parent[x] = findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= n; i++) {
+            parent[i] = i;
+        }
+
+        // 각 연산을 하나씩 확인 
+        for (int i = 0; i < m; i++) {
+            int oper = sc.nextInt();
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            // 합집합(Union) 연산인 경우
+            if (oper == 0) {
+                unionParent(a, b);
+            }
+            // 찾기(Find) 연산인 경우
+            else if (oper == 1) {
+                if (findParent(a) == findParent(b)) {
+                    System.out.println("YES");
+                }
+                else {
+                    System.out.println("NO");
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/10/7.py b/10/7.py
index 6018216..d03509f 100644
--- a/10/7.py
+++ b/10/7.py
@@ -14,35 +14,22 @@ def union_parent(parent, a, b):
     else:
         parent[a] = b
 
-# 노드의 개수와 간선(Union 연산)의 개수 입력 받기
-v, e = map(int, input().split())
-parent = [0] * (v + 1) # 부모 테이블 초기화하기
-
-# 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
-edges = []
-result = 0
+n, m = map(int, input().split())
+parent = [0] * (n + 1) # 부모 테이블 초기화
 
 # 부모 테이블상에서, 부모를 자기 자신으로 초기화
-for i in range(1, v + 1):
+for i in range(0, n + 1):
     parent[i] = i
 
-# 모든 간선에 대한 정보를 입력 받기
-for _ in range(e):
-    a, b, cost = map(int, input().split())
-    # 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
-    edges.append((cost, a, b))
-
-# 간선을 비용순으로 정렬
-edges.sort()
-last = 0 # 최소 신장 트리에 포함되는 간선 중에서 가장 비용이 큰 간선
-
-# 간선을 하나씩 확인하며
-for edge in edges:
-    cost, a, b = edge
-    # 사이클이 발생하지 않는 경우에만 집합에 포함
-    if find_parent(parent, a) != find_parent(parent, b):
+# 각 연산을 하나씩 확인
+for i in range(m):
+    oper, a, b = map(int, input().split())
+    # 합치합(Union) 연산인 경우
+    if oper == 0:
         union_parent(parent, a, b)
-        result += cost
-        last = cost
-
-print(result - last)
+    # 찾기(Find) 연산인 경우
+    elif oper == 1:
+        if find_parent(parent, a) == find_parent(parent, b):
+            print('YES')
+        else:
+            print('NO')
diff --git a/10/8.cpp b/10/8.cpp
new file mode 100644
index 0000000..e696b1c
--- /dev/null
+++ b/10/8.cpp
@@ -0,0 +1,61 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수와 간선(Union 연산)의 개수 입력받기
+int v, e;
+int parent[100001]; // 부모 테이블 초기화
+// 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+vector<pair<int, pair<int, int> > > edges;
+int result = 0;
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return parent[x] = findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> v >> e;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= v; i++) {
+        parent[i] = i;
+    }
+
+    // 모든 간선에 대한 정보를 입력 받기
+    for (int i = 0; i < e; i++) {
+        int a, b, cost;
+        cin >> a >> b >> cost;
+        // 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
+        edges.push_back({cost, {a, b}});
+    }
+
+    // 간선을 비용순으로 정렬
+    sort(edges.begin(), edges.end());
+    int last = 0; // 최소 신장 트리에 포함되는 간선 중에서 가장 비용이 큰 간선
+
+    // 간선을 하나씩 확인하며
+    for (int i = 0; i < edges.size(); i++) {
+        int cost = edges[i].first;
+        int a = edges[i].second.first;
+        int b = edges[i].second.second;
+        // 사이클이 발생하지 않는 경우에만 집합에 포함
+        if (findParent(a) != findParent(b)) {
+            unionParent(a, b);
+            result += cost;
+            last = cost;
+        }
+    }
+
+    cout << result - last << '\n';
+}
\ No newline at end of file
diff --git a/10/8.java b/10/8.java
new file mode 100644
index 0000000..70ea414
--- /dev/null
+++ b/10/8.java
@@ -0,0 +1,100 @@
+import java.util.*;
+
+class Edge implements Comparable<Edge> {
+
+    private int distance;
+    private int nodeA;
+    private int nodeB;
+
+    public Edge(int distance, int nodeA, int nodeB) {
+        this.distance = distance;
+        this.nodeA = nodeA;
+        this.nodeB = nodeB;
+    }
+
+    public int getDistance() {
+        return this.distance;
+    }
+
+    public int getNodeA() {
+        return this.nodeA;
+    }
+
+    public int getNodeB() {
+        return this.nodeB;
+    }
+
+    // 거리(비용)가 짧은 것이 높은 우선순위를 가지도록 설정
+    @Override
+    public int compareTo(Edge other) {
+        if (this.distance < other.distance) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+
+    // 노드의 개수(V)와 간선(Union 연산)의 개수(E)
+    public static int v, e;
+    public static int[] parent = new int[100001]; // 부모 테이블 초기화
+    // 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+    public static ArrayList<Edge> edges = new ArrayList<>();
+    public static int result = 0;
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return parent[x] = findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        v = sc.nextInt();
+        e = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= v; i++) {
+            parent[i] = i;
+        }
+
+        // 모든 간선에 대한 정보를 입력 받기
+        for (int i = 0; i < e; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            int cost = sc.nextInt();
+            // 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
+            edges.add(new Edge(cost, a, b));
+        }
+
+        // 간선을 비용순으로 정렬
+        Collections.sort(edges);
+        int last = 0; // 최소 신장 트리에 포함되는 간선 중에서 가장 비용이 큰 간선
+
+        // 간선을 하나씩 확인하며
+        for (int i = 0; i < edges.size(); i++) {
+            int cost = edges.get(i).getDistance();
+            int a = edges.get(i).getNodeA();
+            int b = edges.get(i).getNodeB();
+            // 사이클이 발생하지 않는 경우에만 집합에 포함
+            if (findParent(a) != findParent(b)) {
+                unionParent(a, b);
+                result += cost;
+                last = cost;
+            }
+        }
+
+        System.out.println(result - last);
+    }
+}
\ No newline at end of file
diff --git a/10/8.py b/10/8.py
index a80c6cc..f709693 100644
--- a/10/8.py
+++ b/10/8.py
@@ -1,47 +1,48 @@
-from collections import deque
-import copy
-
-# 노드의 개수 입력 받기
-v = int(input())
-# 모든 노드에 대한 진입차수는 0으로 초기화
-indegree = [0] * (v + 1)
-# 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트(그래프) 초기화
-graph = [[] for i in range(v + 1)]
-# 각 강의 시간을 0으로 초기화
-time = [0] * (v + 1)
-
-# 방향 그래프의 모든 간선 정보를 입력 받기
+# 특정 원소가 속한 집합을 찾기
+def find_parent(parent, x):
+    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if parent[x] != x:
+        parent[x] = find_parent(parent, parent[x])
+    return parent[x]
+
+# 두 원소가 속한 집합을 합치기
+def union_parent(parent, a, b):
+    a = find_parent(parent, a)
+    b = find_parent(parent, b)
+    if a < b:
+        parent[b] = a
+    else:
+        parent[a] = b
+
+# 노드의 개수와 간선(Union 연산)의 개수 입력받기
+v, e = map(int, input().split())
+parent = [0] * (v + 1) # 부모 테이블 초기화
+
+# 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+edges = []
+result = 0
+
+# 부모 테이블상에서, 부모를 자기 자신으로 초기화
 for i in range(1, v + 1):
-    data = list(map(int, input().split()))
-    time[i] = data[0] # 첫 번째 수는 시간 정보를 담고 있음
-    for x in data[1:-1]:
-        indegree[i] += 1
-        graph[x].append(i)
-
-# 위상 정렬 함수
-def topology_sort():
-    result = copy.deepcopy(time) # 알고리즘 수행 결과를 담을 리스트
-    q = deque() # 큐 기능을 위한 deque 라이브러리 사용
-
-    # 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
-    for i in range(1, v + 1):
-        if indegree[i] == 0:
-            q.append(i)
-
-    # 큐가 빌 때까지 반복
-    while q:
-        # 큐에서 원소 꺼내기
-        now = q.popleft()
-        # 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
-        for i in graph[now]:
-            result[i] = max(result[i], result[now] + time[i])
-            indegree[i] -= 1
-            # 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
-            if indegree[i] == 0:
-                q.append(i)
-
-    # 위상 정렬을 수행한 결과 출력
-    for i in range(1, v + 1):
-        print(result[i])
-
-topology_sort()
+    parent[i] = i
+
+# 모든 간선에 대한 정보를 입력받기
+for _ in range(e):
+    a, b, cost = map(int, input().split())
+    # 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
+    edges.append((cost, a, b))
+
+# 간선을 비용순으로 정렬
+edges.sort()
+last = 0 # 최소 신장 트리에 포함되는 간선 중에서 가장 비용이 큰 간선
+
+# 간선을 하나씩 확인하며
+for edge in edges:
+    cost, a, b = edge
+    # 사이클이 발생하지 않는 경우에만 집합에 포함
+    if find_parent(parent, a) != find_parent(parent, b):
+        union_parent(parent, a, b)
+        result += cost
+        last = cost
+
+print(result - last)
diff --git a/10/9.cpp b/10/9.cpp
new file mode 100644
index 0000000..76f88bd
--- /dev/null
+++ b/10/9.cpp
@@ -0,0 +1,71 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수(V)
+int v;
+// 모든 노드에 대한 진입차수는 0으로 초기화
+int indegree[501];
+// 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
+vector<int> graph[501];
+// 각 강의 시간을 0으로 초기화
+int times[501]; 
+
+// 위상 정렬 함수 
+void topologySort() {
+    vector<int> result(501); // 알고리즘 수행 결과를 담을 리스트 
+    for (int i = 1; i <= v; i++) {
+        result[i] = times[i];
+    } 
+    
+    queue<int> q; // 큐 라이브러리 사용
+
+    // 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
+    for (int i = 1; i <= v; i++) {
+        if (indegree[i] == 0) {
+            q.push(i);
+        }
+    }
+
+    // 큐가 빌 때까지 반복
+    while (!q.empty()) {
+        // 큐에서 원소 꺼내기
+        int now = q.front();
+        q.pop();
+        // 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
+        for (int i = 0; i < graph[now].size(); i++) {
+            result[graph[now][i]] = max(result[graph[now][i]], result[now] + times[graph[now][i]]);
+            indegree[graph[now][i]] -= 1;
+            // 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
+            if (indegree[graph[now][i]] == 0) {
+                q.push(graph[now][i]);
+            }
+        }
+    }
+
+    // 위상 정렬을 수행한 결과 출력
+    for (int i = 1; i <= v; i++) {
+        cout << result[i] << '\n';
+    }
+}
+
+int main(void) {
+    cin >> v;
+
+    // 방향 그래프의 모든 간선 정보를 입력받기
+    for (int i = 1; i <= v; i++) {
+        // 첫 번째 수는 시간 정보를 담고 있음 
+        int x;
+        cin >> x;
+        times[i] = x;
+        // 해당 강의를 듣기 위해 먼저 들어야 하는 강의들의 번호 입력 
+        while (true) {
+            cin >> x;
+            if (x == -1) break;
+            indegree[i] += 1;
+            graph[x].push_back(i);
+        }
+    }
+
+    topologySort();
+}
diff --git a/10/9.java b/10/9.java
new file mode 100644
index 0000000..f9dce6f
--- /dev/null
+++ b/10/9.java
@@ -0,0 +1,77 @@
+import java.util.*;
+
+public class Main {
+
+    // 노드의 개수(V)
+    public static int v;
+    // 모든 노드에 대한 진입차수는 0으로 초기화
+    public static int[] indegree = new int[501];
+    // 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
+    public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
+    // 각 강의 시간을 0으로 초기화
+    public static int[] times = new int[501];
+
+    // 위상 정렬 함수
+    public static void topologySort() {
+        int[] result = new int[501]; // 알고리즘 수행 결과를 담을 배열
+        for (int i = 1; i <= v; i++) {
+            result[i] = times[i];
+        }
+
+        Queue<Integer> q = new LinkedList<>(); // 큐 라이브러리 사용
+
+        // 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
+        for (int i = 1; i <= v; i++) {
+            if (indegree[i] == 0) {
+                q.offer(i);
+            }
+        }
+
+        // 큐가 빌 때까지 반복
+        while (!q.isEmpty()) {
+            // 큐에서 원소 꺼내기
+            int now = q.poll();
+            // 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
+            for (int i = 0; i < graph.get(now).size(); i++) {
+                result[graph.get(now).get(i)] = Math.max(result[graph.get(now).get(i)], result[now] + times[graph.get(now).get(i)]);
+                indegree[graph.get(now).get(i)] -= 1;
+                // 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
+                if (indegree[graph.get(now).get(i)] == 0) {
+                    q.offer(graph.get(now).get(i));
+                }
+            }
+        }
+
+        // 위상 정렬을 수행한 결과 출력
+        for (int i = 1; i <= v; i++) {
+            System.out.println(result[i]);
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        v = sc.nextInt();
+
+        // 그래프 초기화
+        for (int i = 0; i <= v; i++) {
+            graph.add(new ArrayList<Integer>());
+        }
+
+        // 방향 그래프의 모든 간선 정보를 입력받기
+        for (int i = 1; i <= v; i++) {
+            // 첫 번째 수는 시간 정보를 담고 있음 
+            int x = sc.nextInt();
+            times[i] = x;
+            // 해당 강의를 듣기 위해 먼저 들어야 하는 강의들의 번호 입력 
+            while (true) {
+                x = sc.nextInt();
+                if (x == -1) break;
+                indegree[i] += 1;
+                graph.get(x).add(i);
+            }
+        }
+
+        topologySort();
+    }
+}
\ No newline at end of file
diff --git a/10/9.py b/10/9.py
new file mode 100644
index 0000000..9adb0de
--- /dev/null
+++ b/10/9.py
@@ -0,0 +1,47 @@
+from collections import deque
+import copy
+
+# 노드의 개수 입력받기
+v = int(input())
+# 모든 노드에 대한 진입차수는 0으로 초기화
+indegree = [0] * (v + 1)
+# 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트(그래프) 초기화
+graph = [[] for i in range(v + 1)]
+# 각 강의 시간을 0으로 초기화
+time = [0] * (v + 1)
+
+# 방향 그래프의 모든 간선 정보를 입력받기
+for i in range(1, v + 1):
+    data = list(map(int, input().split()))
+    time[i] = data[0] # 첫 번째 수는 시간 정보를 담고 있음
+    for x in data[1:-1]:
+        indegree[i] += 1
+        graph[x].append(i)
+
+# 위상 정렬 함수
+def topology_sort():
+    result = copy.deepcopy(time) # 알고리즘 수행 결과를 담을 리스트
+    q = deque() # 큐 기능을 위한 deque 라이브러리 사용
+
+    # 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
+    for i in range(1, v + 1):
+        if indegree[i] == 0:
+            q.append(i)
+
+    # 큐가 빌 때까지 반복
+    while q:
+        # 큐에서 원소 꺼내기
+        now = q.popleft()
+        # 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
+        for i in graph[now]:
+            result[i] = max(result[i], result[now] + time[i])
+            indegree[i] -= 1
+            # 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
+            if indegree[i] == 0:
+                q.append(i)
+
+    # 위상 정렬을 수행한 결과 출력
+    for i in range(1, v + 1):
+        print(result[i])
+
+topology_sort()
diff --git a/11/1.cpp b/11/1.cpp
new file mode 100644
index 0000000..30a3009
--- /dev/null
+++ b/11/1.cpp
@@ -0,0 +1,31 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n;
+vector<int> arr;
+
+int main(void) {
+    cin >> n;
+
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+
+    sort(arr.begin(), arr.end());
+
+    int result = 0; // 총 그룹의 수
+    int count = 0; // 현재 그룹에 포함된 모험가의 수
+
+    for (int i = 0; i < n; i++) { // 공포도를 낮은 것부터 하나씩 확인하며
+        count += 1; // 현재 그룹에 해당 모험가를 포함시키기
+        if (count >= arr[i]) { // 현재 그룹에 포함된 모험가의 수가 현재의 공포도 이상이라면, 그룹 결성
+            result += 1; // 총 그룹의 수 증가시키기
+            count = 0; // 현재 그룹에 포함된 모험가의 수 초기화
+        }
+    }
+
+    cout << result << '\n'; // 총 그룹의 수 출력
+}
diff --git a/11/1.java b/11/1.java
new file mode 100644
index 0000000..a6db606
--- /dev/null
+++ b/11/1.java
@@ -0,0 +1,31 @@
+import java.util.*;
+
+public class Main {
+
+    public static int n;
+    public static ArrayList<Integer> arrayList = new ArrayList<>();
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        n = sc.nextInt();
+
+        for (int i = 0; i < n; i++) {
+            arrayList.add(sc.nextInt());
+        }
+
+        Collections.sort(arrayList);
+
+        int result = 0; // 총 그룹의 수
+        int count = 0; // 현재 그룹에 포함된 모험가의 수
+
+        for (int i = 0; i < n; i++) { // 공포도를 낮은 것부터 하나씩 확인하며
+            count += 1; // 현재 그룹에 해당 모험가를 포함시키기
+            if (count >= arrayList.get(i)) { // 현재 그룹에 포함된 모험가의 수가 현재의 공포도 이상이라면, 그룹 결성
+                result += 1; // 총 그룹의 수 증가시키기
+                count = 0; // 현재 그룹에 포함된 모험가의 수 초기화
+            }
+        }
+
+        System.out.println(result);
+    }
+}
\ No newline at end of file
diff --git a/11/2.cpp b/11/2.cpp
new file mode 100644
index 0000000..9f2de1e
--- /dev/null
+++ b/11/2.cpp
@@ -0,0 +1,25 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+string str;
+
+int main(void) {
+    cin >> str;
+
+    // 첫 번째 문자를 숫자로 변경한 값을 대입
+    long long result = str[0] - '0';
+
+    for (int i = 1; i < str.size(); i++) {
+        // 두 수 중에서 하나라도 '0' 혹은 '1'인 경우, 곱하기보다는 더하기 수행
+        int num = str[i] - '0';
+        if (num <= 1 || result <= 1) {
+            result += num;
+        }
+        else {
+            result *= num;
+        }
+    }
+
+    cout << result << '\n';
+}
diff --git a/11/2.java b/11/2.java
new file mode 100644
index 0000000..e77eae5
--- /dev/null
+++ b/11/2.java
@@ -0,0 +1,25 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        String str = sc.next();
+
+        // 첫 번째 문자를 숫자로 변경한 값을 대입
+        long result = str.charAt(0) - '0';
+        
+        for (int i = 1; i < str.length(); i++) {
+            // 두 수 중에서 하나라도 '0' 혹은 '1'인 경우, 곱하기보다는 더하기 수행
+            int num = str.charAt(i) - '0';
+            if (num <= 1 || result <= 1) {
+                result += num;
+            }
+            else {
+                result *= num;
+            }
+        }
+
+        System.out.println(result);
+    }
+}
\ No newline at end of file
diff --git a/11/2.py b/11/2.py
index d629e2f..f6e6294 100644
--- a/11/2.py
+++ b/11/2.py
@@ -1,13 +1,14 @@
-str = input()
+data = input()
 
 # 첫 번째 문자를 숫자로 변경하여 대입
-result = int(str[0])
+result = int(data[0])
 
-for i in range(1, len(str)):
+for i in range(1, len(data)):
     # 두 수 중에서 하나라도 '0' 혹은 '1'인 경우, 곱하기보다는 더하기 수행
-    if str[i] == '0' or str[i] == '1' or result <= 1:
-        result += int(str[i])
+    num = int(data[i])
+    if num <= 1 or result <= 1:
+        result += num
     else:
-        result *= int(str[i])
+        result *= num
 
 print(result)
diff --git a/11/3.cpp b/11/3.cpp
new file mode 100644
index 0000000..29445d8
--- /dev/null
+++ b/11/3.cpp
@@ -0,0 +1,31 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+string str;
+int count0 = 0; // 전부 0으로 바꾸는 경우
+int count1 = 0; // 전부 1로 바꾸는 경우
+
+int main(void) {
+    cin >> str;
+
+    // 첫 번째 원소에 대해서 처리
+    if (str[0] == '1') {
+        count0 += 1;
+    }
+    else {
+        count1 += 1;
+    }
+
+    // 두 번째 원소부터 모든 원소를 확인하며
+    for (int i = 0; i < str.size() - 1; i++) {
+        if (str[i] != str[i + 1]) {
+            // 다음 수에서 1로 바뀌는 경우
+            if (str[i + 1] == '1') count0 += 1;
+            // 다음 수에서 0으로 바뀌는 경우
+            else count1 += 1;
+        }
+    }
+
+    cout << min(count0, count1) << '\n';
+}
\ No newline at end of file
diff --git a/11/3.java b/11/3.java
new file mode 100644
index 0000000..d757686
--- /dev/null
+++ b/11/3.java
@@ -0,0 +1,33 @@
+import java.util.*;
+
+public class Main {
+
+    public static String str;
+    public static int count0 = 0; // 전부 0으로 바꾸는 경우
+    public static int count1 = 0; // 전부 1로 바꾸는 경우
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        str = sc.next();
+
+        // 첫 번째 원소에 대해서 처리
+        if (str.charAt(0) == '1') {
+            count0 += 1;
+        }
+        else {
+            count1 += 1;
+        }
+
+        // 두 번째 원소부터 모든 원소를 확인하며
+        for (int i = 0; i < str.length() - 1; i++) {
+            if (str.charAt(i) != str.charAt(i + 1)) {
+                // 다음 수에서 1로 바뀌는 경우
+                if (str.charAt(i + 1) == '1') count0 += 1;
+                // 다음 수에서 0으로 바뀌는 경우
+                else count1 += 1;
+            }
+        }
+
+        System.out.println(Math.min(count0, count1));
+    }
+}
\ No newline at end of file
diff --git a/11/4.cpp b/11/4.cpp
new file mode 100644
index 0000000..9994220
--- /dev/null
+++ b/11/4.cpp
@@ -0,0 +1,28 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n;
+vector<int> arr;
+
+int main(void) {
+    cin >> n;
+
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+
+    sort(arr.begin(), arr.end());
+
+    int target = 1;
+    for (int i = 0; i < n; i++) {
+        // 만들 수 없는 금액을 찾았을 때 반복 종료
+        if (target < arr[i]) break;
+        target += arr[i];
+    }
+
+    // 만들 수 없는 금액 출력
+    cout << target << '\n';
+}
\ No newline at end of file
diff --git a/11/4.java b/11/4.java
new file mode 100644
index 0000000..7d8adbb
--- /dev/null
+++ b/11/4.java
@@ -0,0 +1,27 @@
+import java.util.*;
+
+public class Main {
+
+    public static int n;
+    public static ArrayList<Integer> arrayList = new ArrayList<>();
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        n = sc.nextInt();
+
+        for (int i = 0; i < n; i++) {
+            arrayList.add(sc.nextInt());
+        }
+
+        Collections.sort(arrayList);
+
+        int target = 1;
+        for (int i = 0; i < n; i++) {
+            // 만들 수 없는 금액을 찾았을 때 반복 종료
+            if (target < arrayList.get(i)) break;
+            target += arrayList.get(i);
+        }
+
+        System.out.println(target);
+    }
+}
\ No newline at end of file
diff --git a/11/5.cpp b/11/5.cpp
new file mode 100644
index 0000000..1935e09
--- /dev/null
+++ b/11/5.cpp
@@ -0,0 +1,27 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, m;
+// 1부터 10까지의 무게를 담을 수 있는 배열
+int arr[11];
+
+int main(void) {
+    cin >> n >> m;
+
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr[x] += 1;
+    }
+
+    int result = 0;
+
+    // 1부터 m까지의 각 무게에 대하여 처리
+    for (int i = 1; i <= m; i++) {
+        n -= arr[i]; // 무게가 i인 볼링공의 개수(A가 선택할 수 있는 개수) 제외
+        result += arr[i] * n; // B가 선택하는 경우의 수와 곱해주기
+    }
+
+    cout << result << '\n';
+}
\ No newline at end of file
diff --git a/11/5.java b/11/5.java
new file mode 100644
index 0000000..98b58d4
--- /dev/null
+++ b/11/5.java
@@ -0,0 +1,29 @@
+import java.util.*;
+
+public class Main {
+
+    public static int n, m;
+    // 1부터 10까지의 무게를 담을 수 있는 배열
+    public static int[] arr = new int[11];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        for (int i = 0; i < n; i++) {
+            int x = sc.nextInt();
+            arr[x] += 1;
+        }
+
+        int result = 0;
+
+        // 1부터 m까지의 각 무게에 대하여 처리
+        for (int i = 1; i <= m; i++) {
+            n -= arr[i]; // 무게가 i인 볼링공의 개수(A가 선택할 수 있는 개수) 제외
+            result += arr[i] * n; // B가 선택하는 경우의 수와 곱해주기
+        }
+
+        System.out.println(result);
+    }
+}
\ No newline at end of file
diff --git a/11/6.cpp b/11/6.cpp
new file mode 100644
index 0000000..112100d
--- /dev/null
+++ b/11/6.cpp
@@ -0,0 +1,47 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+bool compare(pair<int, int> a, pair<int, int> b) {
+    return a.second < b.second;
+}
+
+int solution(vector<int> food_times, long long k) {
+    // 전체 음식을 먹는 시간보다 k가 크거나 같다면 -1
+    long long summary = 0;
+    for (int i = 0; i < food_times.size(); i++) {
+        summary += food_times[i];
+    }
+    if (summary <= k) return -1;
+    
+    // 시간이 작은 음식부터 빼야 하므로 우선순위 큐를 이용
+    priority_queue<pair<int, int> > pq;
+    for (int i = 0; i < food_times.size(); i++) {
+        // (음식 시간, 음식 번호) 형태로 우선순위 큐에 삽입
+        pq.push({-food_times[i], i + 1});
+    }
+    
+    summary = 0; // 먹기 위해 사용한 시간
+    long long previous = 0; // 직전에 다 먹은 음식 시간
+    long long length = food_times.size(); // 남은 음식의 개수
+
+    // summary + (현재의 음식 시간 - 이전 음식 시간) * 현재 음식 개수와 k 비교
+    while (summary + ((-pq.top().first - previous) * length) <= k) {
+        int now = -pq.top().first;
+        pq.pop();
+        summary += (now - previous) * length;
+        length -= 1; // 다 먹은 음식 제외
+        previous = now; // 이전 음식 시간 재설정
+    }
+
+    // 남은 음식 중에서 몇 번째 음식인지 확인하여 출력
+    vector<pair<int, int> > result;
+    while (!pq.empty()) {
+        int food_time = -pq.top().first;
+        int num = pq.top().second;
+        pq.pop();
+        result.push_back({food_time, num});
+    }
+    sort(result.begin(), result.end(), compare); // 음식의 번호 기준으로 정렬
+    return result[(k - summary) % length].second;
+}
\ No newline at end of file
diff --git a/11/6.java b/11/6.java
new file mode 100644
index 0000000..33fe539
--- /dev/null
+++ b/11/6.java
@@ -0,0 +1,70 @@
+import java.util.*;
+
+class Food implements Comparable<Food> {
+
+    private int time;
+    private int index;
+
+    public Food(int time, int index) {
+        this.time = time;
+        this.index = index;
+    }
+
+    public int getTime() {
+        return this.time;
+    }
+
+    public int getIndex() {
+        return this.index;
+    }
+
+    // 시간이 짧은 것이 높은 우선순위를 가지도록 설정
+    @Override
+    public int compareTo(Food other) {
+        return Integer.compare(this.time, other.time);
+    }
+}
+
+class Solution {
+    public int solution(int[] food_times, long k) {
+        // 전체 음식을 먹는 시간보다 k가 크거나 같다면 -1
+        long summary = 0;
+        for (int i = 0; i < food_times.length; i++) {
+            summary += food_times[i];
+        }
+        if (summary <= k) return -1;
+
+        // 시간이 작은 음식부터 빼야 하므로 우선순위 큐를 이용
+        PriorityQueue<Food> pq = new PriorityQueue<>();
+        for (int i = 0; i < food_times.length; i++) {
+            // (음식 시간, 음식 번호) 형태로 우선순위 큐에 삽입
+            pq.offer(new Food(food_times[i], i + 1));
+        }
+
+        summary = 0; // 먹기 위해 사용한 시간
+        long previous = 0; // 직전에 다 먹은 음식 시간
+        long length = food_times.length; // 남은 음식의 개수
+
+        // summary + (현재의 음식 시간 - 이전 음식 시간) * 현재 음식 개수와 k 비교
+        while (summary + ((pq.peek().getTime() - previous) * length) <= k) {
+            int now = pq.poll().getTime();
+            summary += (now - previous) * length;
+            length -= 1; // 다 먹은 음식 제외
+            previous = now; // 이전 음식 시간 재설정
+        }
+
+        // 남은 음식 중에서 몇 번째 음식인지 확인하여 출력
+        ArrayList<Food> result = new ArrayList<>();
+        while (!pq.isEmpty()) {
+            result.add(pq.poll());
+        }
+        // 음식의 번호 기준으로 정렬
+        Collections.sort(result, new Comparator<Food>() { 
+            @Override
+            public int compare(Food a, Food b) {
+                return Integer.compare(a.getIndex(), b.getIndex());
+            }
+        });
+        return result.get((int) ((k - summary) % length)).getIndex();
+    }
+}
\ No newline at end of file
diff --git a/11/6.py b/11/6.py
index 70e8417..3f339d7 100644
--- a/11/6.py
+++ b/11/6.py
@@ -23,5 +23,5 @@ def solution(food_times, k):
         previous = now # 이전 음식 시간 재설정
 
     # 남은 음식 중에서 몇 번째 음식인지 확인하여 출력
-    result = sorted(q, key =lambda x: x[1]) # 음식의 번호 기준으로 정렬
+    result = sorted(q, key=lambda x: x[1]) # 음식의 번호 기준으로 정렬
     return result[(k - sum_value) % length][1]
diff --git a/12/1.cpp b/12/1.cpp
new file mode 100644
index 0000000..b34c168
--- /dev/null
+++ b/12/1.cpp
@@ -0,0 +1,24 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+string str;
+int summary = 0;
+
+int main(void) {
+    cin >> str;
+
+    // 왼쪽 부분의 자릿수의 합 더하기
+    for (int i = 0; i < str.size() / 2; i++) {
+        summary += str[i] - '0';
+    }
+
+    // 오른쪽 부분의 자릿수의 합 빼기
+    for (int i = str.size() / 2; i < str.size(); i++) {
+        summary -= str[i] - '0';
+    }
+
+    // 왼쪽 부분과 오른쪽 부분의 자릿수 합이 동일한지 검사
+    if (summary == 0) cout << "LUCKY" << '\n';
+    else cout << "READY" << '\n';
+}
\ No newline at end of file
diff --git a/12/1.java b/12/1.java
new file mode 100644
index 0000000..947efa1
--- /dev/null
+++ b/12/1.java
@@ -0,0 +1,26 @@
+import java.util.*;
+
+public class Main {
+
+    public static String str;
+    public static int summary = 0;
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        str = sc.next();
+
+        // 왼쪽 부분의 자릿수의 합 더하기
+        for (int i = 0; i < str.length() / 2; i++) {
+            summary += str.charAt(i) - '0';
+        }
+
+        // 오른쪽 부분의 자릿수의 합 빼기
+        for (int i = str.length() / 2; i < str.length(); i++) {
+            summary -= str.charAt(i) - '0';
+        }
+
+        // 왼쪽 부분과 오른쪽 부분의 자릿수 합이 동일한지 검사
+        if (summary == 0) System.out.println("LUCKY");
+        else System.out.println("READY");
+    }
+}
\ No newline at end of file
diff --git a/12/2.cpp b/12/2.cpp
new file mode 100644
index 0000000..aee809a
--- /dev/null
+++ b/12/2.cpp
@@ -0,0 +1,35 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+string str;
+vector<char> result;
+int value = 0;
+
+int main(void) {
+    cin >> str;
+
+    // 문자를 하나씩 확인하며
+    for (int i = 0; i < str.size(); i++) {
+        // 알파벳인 경우 결과 리스트에 삽입
+        if (isalpha(str[i])) {
+            result.push_back(str[i]);
+        }
+        // 숫자는 따로 더하기
+        else {
+            value += str[i] - '0';
+        }
+    }
+
+    // 알파벳을 오름차순으로 정렬
+    sort(result.begin(), result.end());
+
+    // 알파벳을 차례대로 출력
+    for (int i = 0; i < result.size(); i++) {
+        cout << result[i];
+    }
+
+    // 숫자가 하나라도 존재하는 경우 가장 뒤에 출력
+    if (value != 0) cout << value;
+    cout << '\n';
+}
diff --git a/12/2.java b/12/2.java
new file mode 100644
index 0000000..40b8c91
--- /dev/null
+++ b/12/2.java
@@ -0,0 +1,37 @@
+import java.util.*;
+
+public class Main {
+
+    public static String str;
+    public static ArrayList<Character> result = new ArrayList<Character>();
+    public static int value = 0;
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        str = sc.next();
+
+        // 문자를 하나씩 확인하며
+        for (int i = 0; i < str.length(); i++) {
+            // 알파벳인 경우 결과 리스트에 삽입
+            if (Character.isLetter(str.charAt(i))) {
+                result.add(str.charAt(i));
+            }
+            // 숫자는 따로 더하기
+            else {
+                value += str.charAt(i) - '0';
+            }
+        }
+
+        // 알파벳을 오름차순으로 정렬
+        Collections.sort(result);
+
+        // 알파벳을 차례대로 출력
+        for (int i = 0; i < result.size(); i++) {
+            System.out.print(result.get(i));
+        }
+
+        // 숫자가 하나라도 존재하는 경우 가장 뒤에 출력
+        if (value != 0) System.out.print(value);
+        System.out.println();
+    }
+}
\ No newline at end of file
diff --git a/12/2.py b/12/2.py
index e8b66fe..9e9935f 100644
--- a/12/2.py
+++ b/12/2.py
@@ -18,5 +18,5 @@
 if value != 0:
     result.append(str(value))
 
-# 최종 결과 출력 (리스트를 문자열로 변환하여 출력)
+# 최종 결과 출력(리스트를 문자열로 변환하여 출력)
 print(''.join(result))
diff --git a/12/3.cpp b/12/3.cpp
new file mode 100644
index 0000000..f7232bd
--- /dev/null
+++ b/12/3.cpp
@@ -0,0 +1,29 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int solution(string s) {
+    int answer = s.size();
+    // 1개 단위(step)부터 압축 단위를 늘려가며 확인
+    for (int step = 1; step < s.size() / 2 + 1; step++) {
+        string compressed = "";
+        string prev = s.substr(0, step); // 앞에서부터 step만큼의 문자열 추출
+        int cnt = 1;
+        // 단위(step) 크기만큼 증가시키며 이전 문자열과 비교
+        for (int j = step; j < s.size(); j += step) {
+            // 이전 상태와 동일하다면 압축 횟수(count) 증가
+            if (prev == s.substr(j, step)) cnt += 1;
+            // 다른 문자열이 나왔다면(더 이상 압축하지 못하는 경우라면)
+            else {
+                compressed += (cnt >= 2)? to_string(cnt) + prev : prev;
+                prev = s.substr(j, step); // 다시 상태 초기화
+                cnt = 1;
+            }
+        }
+        // 남아있는 문자열에 대해서 처리
+        compressed += (cnt >= 2)? to_string(cnt) + prev : prev;
+        // 만들어지는 압축 문자열이 가장 짧은 것이 정답
+        answer = min(answer, (int)compressed.size());
+    }
+    return answer;
+}
diff --git a/12/3.java b/12/3.java
new file mode 100644
index 0000000..17f2365
--- /dev/null
+++ b/12/3.java
@@ -0,0 +1,38 @@
+import java.util.*;
+
+class Solution {
+
+    public int solution(String s) {
+        int answer = s.length();
+        // 1개 단위(step)부터 압축 단위를 늘려가며 확인
+        for (int step = 1; step < s.length() / 2 + 1; step++) {
+            String compressed = "";
+            String prev = s.substring(0, step); // 앞에서부터 step만큼의 문자열 추출
+            int cnt = 1;
+            // 단위(step) 크기만큼 증가시키며 이전 문자열과 비교
+            for (int j = step; j < s.length(); j += step) {
+                // 이전 상태와 동일하다면 압축 횟수(count) 증가
+                String sub = "";
+                for (int k = j; k < j + step; k++) {
+                    if (k < s.length()) sub += s.charAt(k);
+                }
+                if (prev.equals(sub)) cnt += 1;
+                // 다른 문자열이 나왔다면(더 이상 압축하지 못하는 경우라면)
+                else {
+                    compressed += (cnt >= 2)? cnt + prev : prev;
+                    sub = "";
+                    for (int k = j; k < j + step; k++) {
+                        if (k < s.length()) sub += s.charAt(k);
+                    }
+                    prev = sub; // 다시 상태 초기화
+                    cnt = 1;
+                }
+            }
+            // 남아있는 문자열에 대해서 처리
+            compressed += (cnt >= 2)? cnt + prev : prev;
+            // 만들어지는 압축 문자열이 가장 짧은 것이 정답
+            answer = Math.min(answer, compressed.length());
+        }
+        return answer;
+    } 
+}
\ No newline at end of file
diff --git a/12/3.py b/12/3.py
index bc7601a..94d712b 100644
--- a/12/3.py
+++ b/12/3.py
@@ -10,7 +10,7 @@ def solution(s):
             # 이전 상태와 동일하다면 압축 횟수(count) 증가
             if prev == s[j:j + step]:
                 count += 1
-            # 다른 문자열이 나왔다면 (더 이상 압축하지 못하는 경우라면)
+            # 다른 문자열이 나왔다면(더 이상 압축하지 못하는 경우라면)
             else:
                 compressed += str(count) + prev if count >= 2 else prev
                 prev = s[j:j + step] # 다시 상태 초기화
diff --git a/12/4.cpp b/12/4.cpp
new file mode 100644
index 0000000..cf888d1
--- /dev/null
+++ b/12/4.cpp
@@ -0,0 +1,66 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 2차원 리스트 90도 회전하기
+vector<vector<int> > rotateMatrixBy90Degree(vector<vector<int> > a) {
+    int n = a.size(); // 행 길이 계산
+    int m = a[0].size(); // 열 길이 계산
+    vector<vector<int> > result(n, vector<int>(m)); // 결과 리스트
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < m; j++) {
+            result[j][n - i - 1] = a[i][j];
+        }
+    }
+    return result;
+}
+
+// 자물쇠의 중간 부분이 모두 1인지 확인
+bool check(vector<vector<int> > newLock) {
+    int lockLength = newLock.size() / 3;
+    for (int i = lockLength; i < lockLength * 2; i++) {
+        for (int j = lockLength; j < lockLength * 2; j++) {
+            if (newLock[i][j] != 1) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool solution(vector<vector<int> > key, vector<vector<int> > lock) {
+    int n = lock.size();
+    int m = key.size();
+    // 자물쇠의 크기를 기존의 3배로 변환
+    vector<vector<int> > newLock(n * 3, vector<int>(n * 3));
+    // 새로운 자물쇠의 중앙 부분에 기존의 자물쇠 넣기
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < n; j++) {
+            newLock[i + n][j + n] = lock[i][j];
+        }
+    }
+
+    // 4가지 방향에 대해서 확인
+    for (int rotation = 0; rotation < 4; rotation++) {
+        key = rotateMatrixBy90Degree(key); // 열쇠 회전
+        for (int x = 0; x < n * 2; x++) {
+            for (int y = 0; y < n * 2; y++) {
+                // 자물쇠에 열쇠를 끼워 넣기
+                for (int i = 0; i < m; i++) {
+                    for (int j = 0; j < m; j++) {
+                        newLock[x + i][y + j] += key[i][j];
+                    }
+                }
+                // 새로운 자물쇠에 열쇠가 정확히 들어 맞는지 검사
+                if (check(newLock)) return true;
+                // 자물쇠에서 열쇠를 다시 빼기
+                for (int i = 0; i < m; i++) {
+                    for (int j = 0; j < m; j++) {
+                        newLock[x + i][y + j] -= key[i][j];
+                    }
+                }
+            }
+        }
+    }
+    return false;
+}
\ No newline at end of file
diff --git a/12/4.java b/12/4.java
new file mode 100644
index 0000000..4177231
--- /dev/null
+++ b/12/4.java
@@ -0,0 +1,67 @@
+import java.util.*;
+
+class Solution {
+
+    // 2차원 리스트 90도 회전하기
+    public static int[][] rotateMatrixBy90Degree(int[][] a) {
+        int n = a.length;
+        int m = a[0].length;
+        int[][] result = new int[n][m]; // 결과 리스트
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                result[j][n - i - 1] = a[i][j];
+            }
+        }
+        return result;
+    }
+
+    // 자물쇠의 중간 부분이 모두 1인지 확인
+    public static boolean check(int[][] newLock) {
+        int lockLength = newLock.length / 3;
+        for (int i = lockLength; i < lockLength * 2; i++) {
+            for (int j = lockLength; j < lockLength * 2; j++) {
+                if (newLock[i][j] != 1) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public boolean solution(int[][] key, int[][] lock) {
+        int n = lock.length;
+        int m = key.length;
+        // 자물쇠의 크기를 기존의 3배로 변환
+        int[][] newLock = new int[n * 3][n * 3];
+        // 새로운 자물쇠의 중앙 부분에 기존의 자물쇠 넣기
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                newLock[i + n][j + n] = lock[i][j];
+            }
+        }
+
+        // 4가지 방향에 대해서 확인
+        for (int rotation = 0; rotation < 4; rotation++) {
+            key = rotateMatrixBy90Degree(key); // 열쇠 회전
+            for (int x = 0; x < n * 2; x++) {
+                for (int y = 0; y < n * 2; y++) {
+                    // 자물쇠에 열쇠를 끼워 넣기
+                    for (int i = 0; i < m; i++) {
+                        for (int j = 0; j < m; j++) {
+                            newLock[x + i][y + j] += key[i][j];
+                        }
+                    }
+                    // 새로운 자물쇠에 열쇠가 정확히 들어 맞는지 검사
+                    if (check(newLock)) return true;
+                    // 자물쇠에서 열쇠를 다시 빼기
+                    for (int i = 0; i < m; i++) {
+                        for (int j = 0; j < m; j++) {
+                            newLock[x + i][y + j] -= key[i][j];
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/12/4.py b/12/4.py
index bcbc8a5..4ecbaf1 100644
--- a/12/4.py
+++ b/12/4.py
@@ -32,14 +32,14 @@ def solution(key, lock):
         key = rotate_a_matrix_by_90_degree(key) # 열쇠 회전
         for x in range(n * 2):
             for y in range(n * 2):
-                # 자물쇠에 열쇠를 끼워 넣습니다.
+                # 자물쇠에 열쇠를 끼워 넣기
                 for i in range(m):
                     for j in range(m):
                         new_lock[x + i][y + j] += key[i][j]
                 # 새로운 자물쇠에 열쇠가 정확히 들어 맞는지 검사
                 if check(new_lock) == True:
                     return True
-                # 자물쇠에서 열쇠를 다시 빼냅니다.
+                # 자물쇠에서 열쇠를 다시 빼기
                 for i in range(m):
                     for j in range(m):
                         new_lock[x + i][y + j] -= key[i][j]
diff --git a/12/5.cpp b/12/5.cpp
new file mode 100644
index 0000000..d1ee13a
--- /dev/null
+++ b/12/5.cpp
@@ -0,0 +1,85 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, k, l;
+int arr[101][101]; // 맵 정보
+vector<pair<int, char> > info; // 방향 회전 정보
+
+// 처음에는 오른쪽을 보고 있으므로(동, 남, 서, 북)
+int dx[] = {0, 1, 0, -1};
+int dy[] = {1, 0, -1, 0};
+
+int turn(int direction, char c) {
+    if (c == 'L') direction = (direction == 0)? 3 : direction - 1;
+    else direction = (direction + 1) % 4;
+    return direction;
+}
+
+int simulate() {
+    int x = 1, y = 1; // 뱀의 머리 위치
+    arr[x][y] = 2; // 뱀이 존재하는 위치는 2로 표시
+    int direction = 0; // 처음에는 동쪽을 보고 있음
+    int time = 0; // 시작한 뒤에 지난 '초' 시간
+    int index = 0; // 다음에 회전할 정보
+    queue<pair<int, int> > q; // 뱀이 차지하고 있는 위치 정보(꼬리가 앞쪽)
+    q.push({x, y});
+
+    while (true) {
+        int nx = x + dx[direction];
+        int ny = y + dy[direction];
+        // 맵 범위 안에 있고, 뱀의 몸통이 없는 위치라면
+        if (1 <= nx && nx <= n && 1 <= ny && ny <= n && arr[nx][ny] != 2) {
+            // 사과가 없다면 이동 후에 꼬리 제거
+            if (arr[nx][ny] == 0) {
+                arr[nx][ny] = 2;
+                q.push({nx, ny});
+                int px = q.front().first;
+                int py = q.front().second;
+                q.pop();
+                arr[px][py] = 0;
+            }
+            // 사과가 있다면 이동 후에 꼬리 그대로 두기
+            if (arr[nx][ny] == 1) {
+                arr[nx][ny] = 2;
+                q.push({nx, ny});
+            }
+        }
+        // 벽이나 뱀의 몸통과 부딪혔다면
+        else {
+            time += 1;
+            break;
+        }
+        // 다음 위치로 머리를 이동
+        x = nx;
+        y = ny;
+        time += 1;
+        if (index < l && time == info[index].first) { // 회전할 시간인 경우 회전
+            direction = turn(direction, info[index].second);
+            index += 1;
+        }
+    }
+    return time;
+}
+
+int main(void) {
+    cin >> n >> k;
+
+    // 맵 정보(사과 있는 곳은 1로 표시)
+    for (int i = 0; i < k; i++) {
+        int a, b;
+        cin >> a >> b;
+        arr[a][b] = 1;
+    }
+
+    // 방향 회전 정보 입력
+    cin >> l;
+    for (int i = 0; i < l; i++) {
+        int x;
+        char c;
+        cin >> x >> c;
+        info.push_back({x, c});
+    }
+
+    cout << simulate() << '\n';
+}
\ No newline at end of file
diff --git a/12/5.java b/12/5.java
new file mode 100644
index 0000000..026b0c5
--- /dev/null
+++ b/12/5.java
@@ -0,0 +1,126 @@
+import java.util.*;
+
+class Node {
+
+    private int time;
+    private char direction;
+
+    public Node(int time, char direction) {
+        this.time = time;
+        this.direction = direction;
+    }
+
+    public int getTime() {
+        return this.time;
+    }
+
+    public char getDirection() {
+        return this.direction;
+    }
+}
+
+class Position {
+
+    private int x;
+    private int y;
+
+    public Position(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public int getX() {
+        return this.x;
+    }
+
+    public int getY() {
+        return this.y;
+    }
+}
+
+public class Main {
+
+    public static int n, k, l;
+    public static int[][] arr = new int[101][101]; // 맵 정보
+    public static ArrayList<Node> info = new ArrayList<>(); // 방향 회전 정보
+
+    // 처음에는 오른쪽을 보고 있으므로(동, 남, 서, 북)
+    public static int dx[] = {0, 1, 0, -1};
+    public static int dy[] = {1, 0, -1, 0};
+
+    public static int turn(int direction, char c) {
+        if (c == 'L') direction = (direction == 0)? 3 : direction - 1;
+        else direction = (direction + 1) % 4;
+        return direction;
+    }
+
+    public static int simulate() {
+        int x = 1, y = 1; // 뱀의 머리 위치
+        arr[x][y] = 2; // 뱀이 존재하는 위치는 2로 표시
+        int direction = 0; // 처음에는 동쪽을 보고 있음
+        int time = 0; // 시작한 뒤에 지난 '초' 시간
+        int index = 0; // 다음에 회전할 정보
+        // 뱀이 차지하고 있는 위치 정보(꼬리가 앞쪽)
+        Queue<Position> q = new LinkedList<>();
+        q.offer(new Position(x, y));
+        
+        while (true) {
+            int nx = x + dx[direction];
+            int ny = y + dy[direction];
+            // 맵 범위 안에 있고, 뱀의 몸통이 없는 위치라면
+            if (1 <= nx && nx <= n && 1 <= ny && ny <= n && arr[nx][ny] != 2) {
+                // 사과가 없다면 이동 후에 꼬리 제거
+                if (arr[nx][ny] == 0) {
+                    arr[nx][ny] = 2;
+                    q.offer(new Position(nx, ny));
+                    Position prev = q.poll();
+                    arr[prev.getX()][prev.getY()] = 0;
+                }
+                // 사과가 있다면 이동 후에 꼬리 그대로 두기
+                if (arr[nx][ny] == 1) {
+                    arr[nx][ny] = 2;
+                    q.offer(new Position(nx, ny));
+                }
+            }
+            // 벽이나 뱀의 몸통과 부딪혔다면
+            else {
+                time += 1;
+                break;
+            }
+            // 다음 위치로 머리를 이동
+            x = nx;
+            y = ny;
+            time += 1;
+            if (index < l && time == info.get(index).getTime()) { // 회전할 시간인 경우 회전
+                direction = turn(direction, info.get(index).getDirection());
+                index += 1;
+            }
+        }
+        return time;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        n = sc.nextInt();
+        k = sc.nextInt();
+
+        // 맵 정보(사과 있는 곳은 1로 표시)
+        for (int i = 0; i < k; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            arr[a][b] = 1;
+        }
+
+        // 방향 회전 정보 입력
+        l = sc.nextInt();
+        for (int i = 0; i < l; i++) {
+            int x = sc.nextInt();
+            char c = sc.next().charAt(0);
+            info.add(new Node(x, c));
+        }
+  
+        System.out.println(simulate());
+    }
+
+}
\ No newline at end of file
diff --git a/12/5.py b/12/5.py
index 032be5f..e148ca1 100644
--- a/12/5.py
+++ b/12/5.py
@@ -3,7 +3,7 @@
 data = [[0] * (n + 1) for _ in range(n + 1)] # 맵 정보
 info = [] # 방향 회전 정보
 
-# 맵 정보 (사과 있는 곳은 1로 표시)
+# 맵 정보(사과 있는 곳은 1로 표시)
 for _ in range(k):
     a, b = map(int, input().split())
     data[a][b] = 1
@@ -14,7 +14,7 @@
     x, c = input().split()
     info.append((int(x), c))
 
-# 처음에는 오른쪽을 보고 있으므로 (동, 남, 서, 북)
+# 처음에는 오른쪽을 보고 있으므로(동, 남, 서, 북)
 dx = [0, 1, 0, -1]
 dy = [1, 0, -1, 0]
 
@@ -31,7 +31,7 @@ def simulate():
     direction = 0 # 처음에는 동쪽을 보고 있음
     time = 0 # 시작한 뒤에 지난 '초' 시간
     index = 0 # 다음에 회전할 정보
-    q = [(x, y)] # 뱀이 차지하고 있는 위치 정보 (꼬리가 앞쪽)
+    q = [(x, y)] # 뱀이 차지하고 있는 위치 정보(꼬리가 앞쪽)
 
     while True:
         nx = x + dx[direction]
diff --git a/12/6.cpp b/12/6.cpp
new file mode 100644
index 0000000..132730d
--- /dev/null
+++ b/12/6.cpp
@@ -0,0 +1,92 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 현재 설치된 구조물이 '가능한' 구조물인지 확인하는 함수
+bool possible(vector<vector<int> > answer) {
+    for (int i = 0; i < answer.size(); i++) {
+        int x = answer[i][0];
+        int y = answer[i][1];
+        int stuff = answer[i][2];
+        if (stuff == 0) { // 설치된 것이 '기둥'인 경우
+            bool check = false;
+            // '바닥 위'라면 정상
+            if (y == 0) check = true;
+            // '보의 한 쪽 끝 부분 위' 혹은 '다른 기둥 위'라면 정상
+            for (int j = 0; j < answer.size(); j++) {
+                if (x - 1 == answer[j][0] && y == answer[j][1] && 1 == answer[j][2]) {
+                    check = true;
+                }
+                if (x == answer[j][0] && y == answer[j][1] && 1 == answer[j][2]) {
+                    check = true;
+                }
+                if (x == answer[j][0] && y - 1 == answer[j][1] && 0 == answer[j][2]) {
+                    check = true;
+                }
+            }
+            if (!check) return false; // 아니라면 거짓(False) 반환
+        }
+        else if (stuff == 1) { // 설치된 것이 '보'인 경우
+            bool check = false;
+            bool left = false;
+            bool right = false;
+            // '한쪽 끝부분이 기둥 위' 혹은 '양쪽 끝부분이 다른 보와 동시에 연결'이라면 정상
+            for (int j = 0; j < answer.size(); j++) {
+                if (x == answer[j][0] && y - 1 == answer[j][1] && 0 == answer[j][2]) {
+                    check = true;
+                }
+                if (x + 1 == answer[j][0] && y - 1 == answer[j][1] && 0 == answer[j][2]) {
+                    check = true;
+                }
+                if (x - 1 == answer[j][0] && y == answer[j][1] && 1 == answer[j][2]) {
+                    left = true;
+                }
+                if (x + 1 == answer[j][0] && y == answer[j][1] && 1 == answer[j][2]) {
+                    right = true;
+                }
+            }
+            if (left && right) check = true;
+            if (!check) return false; // 아니라면 거짓(False) 반환
+        }
+    }
+    return true;
+}
+
+vector<vector<int> > solution(int n, vector<vector<int> > build_frame) {
+    vector<vector<int> > answer;
+    // 작업(frame)의 개수는 최대 1,000개
+    for (int i = 0; i < build_frame.size(); i++) {
+        int x = build_frame[i][0];
+        int y = build_frame[i][1];
+        int stuff = build_frame[i][2];
+        int operate = build_frame[i][3];
+        if (operate == 0) { // 삭제하는 경우
+            // 일단 삭제를 해 본 뒤에
+            int index = 0;
+            for (int j = 0; j < answer.size(); j++) {
+                if (x == answer[j][0] && y == answer[j][1] && stuff == answer[j][2]) {
+                    index = j;
+                }
+            }
+            vector<int> erased = answer[index];
+            answer.erase(answer.begin() + index);
+            if (!possible(answer)) { // 가능한 구조물인지 확인
+                answer.push_back(erased); // 가능한 구조물이 아니라면 다시 설치
+            }
+        }
+        if (operate == 1) { // 설치하는 경우
+            // 일단 설치를 해 본 뒤에
+            vector<int> inserted;
+            inserted.push_back(x);
+            inserted.push_back(y);
+            inserted.push_back(stuff);
+            answer.push_back(inserted);
+            if (!possible(answer)) { // 가능한 구조물인지 확인
+                answer.pop_back(); // 가능한 구조물이 아니라면 다시 제거
+            }
+        }
+    }
+    // 정렬된 결과를 반환
+    sort(answer.begin(), answer.end());
+    return answer;
+}
\ No newline at end of file
diff --git a/12/6.java b/12/6.java
new file mode 100644
index 0000000..28c4347
--- /dev/null
+++ b/12/6.java
@@ -0,0 +1,143 @@
+import java.util.*;
+
+class Node implements Comparable<Node> {
+
+    private int x;
+    private int y;
+    private int stuff;
+
+    public Node(int x, int y, int stuff) {
+        this.x = x;
+        this.y = y;
+        this.stuff = stuff;
+    }
+
+    public int getX() {
+        return this.x;
+    }
+    
+    public int getY() {
+        return this.y;
+    }
+    
+    public int getStuff() {
+        return this.stuff;
+    }
+    
+    // 정렬 기준 설정 (x, y, stuff 순서대로 오름차순)
+    @Override
+    public int compareTo(Node other) {
+        if (this.x == other.x && this.y == other.y) {
+            return Integer.compare(this.stuff, other.stuff);
+        }
+        if (this.x == other.x) {
+            return Integer.compare(this.y, other.y);
+        }
+        return Integer.compare(this.x, other.x);
+    }
+}
+
+class Solution {
+    
+    // 현재 설치된 구조물이 '가능한' 구조물인지 확인하는 함수
+    public boolean possible(ArrayList<ArrayList<Integer>> answer) {
+        for (int i = 0; i < answer.size(); i++) {
+            int x = answer.get(i).get(0);
+            int y = answer.get(i).get(1);
+            int stuff = answer.get(i).get(2);
+            if (stuff == 0) { // 설치된 것이 '기둥'인 경우
+                boolean check = false;
+                // '바닥 위'라면 정상
+                if (y == 0) check = true;
+                // '보의 한 쪽 끝 부분 위' 혹은 '다른 기둥 위'라면 정상
+                for (int j = 0; j < answer.size(); j++) {
+                    if (x - 1 == answer.get(j).get(0) && y == answer.get(j).get(1) && 1 == answer.get(j).get(2)) {
+                        check = true;
+                    }
+                    if (x == answer.get(j).get(0) && y == answer.get(j).get(1) && 1 == answer.get(j).get(2)) {
+                        check = true;
+                    }
+                    if (x == answer.get(j).get(0) && y - 1 == answer.get(j).get(1) && 0 == answer.get(j).get(2)) {
+                        check = true;
+                    }
+                }
+                if (!check) return false; // 아니라면 거짓(False) 반환
+            }
+            else if (stuff == 1) { // 설치된 것이 '보'인 경우
+                boolean check = false;
+                boolean left = false;
+                boolean right = false;
+                // '한쪽 끝부분이 기둥 위' 혹은 '양쪽 끝부분이 다른 보와 동시에 연결'이라면 정상
+                for (int j = 0; j < answer.size(); j++) {
+                    if (x == answer.get(j).get(0) && y - 1 == answer.get(j).get(1) && 0 == answer.get(j).get(2)) {
+                        check = true;
+                    }
+                    if (x + 1 == answer.get(j).get(0) && y - 1 == answer.get(j).get(1) && 0 == answer.get(j).get(2)) {
+                        check = true;
+                    }
+                    if (x - 1 == answer.get(j).get(0) && y == answer.get(j).get(1) && 1 == answer.get(j).get(2)) {
+                        left = true;
+                    }
+                    if (x + 1 == answer.get(j).get(0) && y == answer.get(j).get(1) && 1 == answer.get(j).get(2)) {
+                        right = true;
+                    }
+                }
+                if (left && right) check = true;
+                if (!check) return false; // 아니라면 거짓(False) 반환
+            }
+        }
+        return true;
+    }
+    
+    public int[][] solution(int n, int[][] build_frame) {
+        ArrayList<ArrayList<Integer>> answer = new ArrayList<ArrayList<Integer>>();
+        // 작업(frame)의 개수는 최대 1,000개
+        for (int i = 0; i < build_frame.length; i++) {
+            int x = build_frame[i][0];
+            int y = build_frame[i][1];
+            int stuff = build_frame[i][2];
+            int operate = build_frame[i][3];
+            if (operate == 0) { // 삭제하는 경우
+                // 일단 삭제를 해 본 뒤에
+                int index = 0;
+                for (int j = 0; j < answer.size(); j++) {
+                    if (x == answer.get(j).get(0) && y == answer.get(j).get(1) && stuff == answer.get(j).get(2)) {
+                        index = j;
+                    }
+                }
+                ArrayList<Integer> erased = answer.get(index);
+                answer.remove(index);
+                if (!possible(answer)) { // 가능한 구조물인지 확인
+                    answer.add(erased); // 가능한 구조물이 아니라면 다시 설치
+                }
+            }
+            if (operate == 1) { // 설치하는 경우
+                // 일단 설치를 해 본 뒤에
+                ArrayList<Integer> inserted = new ArrayList<Integer>();
+                inserted.add(x);
+                inserted.add(y);
+                inserted.add(stuff);
+                answer.add(inserted);
+                if (!possible(answer)) { // 가능한 구조물인지 확인
+                    answer.remove(answer.size() - 1); // 가능한 구조물이 아니라면 다시 제거
+                }
+            }
+        }
+
+        // 정렬 수행
+        ArrayList<Node> ans = new ArrayList<Node>();
+        for (int i = 0; i < answer.size(); i++) {
+            ans.add(new Node(answer.get(i).get(0), answer.get(i).get(1), answer.get(i).get(2)));
+        }
+        Collections.sort(ans);
+        
+        // 배열로 바꾸어 반환
+        int[][] res = new int[ans.size()][3];
+        for (int i = 0; i < ans.size(); i++) {
+            res[i][0] = ans.get(i).getX();
+            res[i][1] = ans.get(i).getY();
+            res[i][2] = ans.get(i).getStuff();
+        }
+        return res;
+    }
+}
diff --git a/12/6.py b/12/6.py
index 6cd5584..d05e3f2 100644
--- a/12/6.py
+++ b/12/6.py
@@ -2,12 +2,12 @@
 def possible(answer):
     for x, y, stuff in answer:
         if stuff == 0: # 설치된 것이 '기둥'인 경우
-            # '바닥 위' 혹은 '보의 한 쪽 끝 부분 위' 혹은 '다른 기둥 위'라면 정상
+            # '바닥 위' 혹은 '보의 한쪽 끝 부분 위' 혹은 '다른 기둥 위'라면 정상
             if y == 0 or [x - 1, y, 1] in answer or [x, y, 1] in answer or [x, y - 1, 0] in answer:
                 continue
             return False # 아니라면 거짓(False) 반환
         elif stuff == 1: # 설치된 것이 '보'인 경우
-            # '한쪽 끝 부분이 기둥 위' 혹은 '양쪽 끝 부분이 다른 보와 동시에 연결'이라면 정상
+            # '한쪽 끝부분이 기둥 위' 혹은 '양쪽 끝부분이 다른 보와 동시에 연결'이라면 정상
             if [x, y - 1, 0] in answer or [x + 1, y - 1, 0] in answer or ([x - 1, y, 1] in answer and [x + 1, y, 1] in answer):
                 continue
             return False # 아니라면 거짓(False) 반환
@@ -18,11 +18,11 @@ def solution(n, build_frame):
     for frame in build_frame: # 작업(frame)의 개수는 최대 1,000개
         x, y, stuff, operate = frame
         if operate == 0: # 삭제하는 경우
-            answer.remove([x, y, stuff]) # 일단 삭제를 해 본 뒤에
+            answer.remove([x, y, stuff]) # 일단 삭제를 해본 뒤에
             if not possible(answer): # 가능한 구조물인지 확인
                 answer.append([x, y, stuff]) # 가능한 구조물이 아니라면 다시 설치
         if operate == 1: # 설치하는 경우
-            answer.append([x, y, stuff]) # 일단 설치를 해 본 뒤에
+            answer.append([x, y, stuff]) # 일단 설치를 해본 뒤에
             if not possible(answer): # 가능한 구조물인지 확인
                 answer.remove([x, y, stuff]) # 가능한 구조물이 아니라면 다시 제거
     return sorted(answer) # 정렬된 결과를 반환
diff --git a/12/7.cpp b/12/7.cpp
new file mode 100644
index 0000000..f04ef83
--- /dev/null
+++ b/12/7.cpp
@@ -0,0 +1,62 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, m;
+int arr[50][50];
+vector<pair<int, int> > chicken;
+vector<pair<int, int> > house;
+
+// 치킨 거리의 합을 계산하는 함수
+int getSum(vector<pair<int, int> > candidates) {
+    int result = 0;
+    // 모든 집에 대하여
+    for (int i = 0; i < house.size(); i++) {
+        int hx = house[i].first;
+        int hy = house[i].second;
+        // 가장 가까운 치킨 집을 찾기
+        int temp = 1e9;
+        for (int j = 0; j < candidates.size(); j++) {
+            int cx = candidates[j].first;
+            int cy = candidates[j].second;
+            temp = min(temp, abs(hx - cx) + abs(hy - cy));
+        }
+        // 가장 가까운 치킨 집까지의 거리를 더하기
+        result += temp;
+    }
+    // 치킨 거리의 합 반환
+    return result;
+} 
+
+int main(void) {
+    cin >> n >> m;
+
+    for (int r = 0; r < n; r++) {
+        for (int c = 0; c < n; c++) {
+            cin >> arr[r][c];
+            if (arr[r][c] == 1) house.push_back({r, c}); // 일반 집
+            else if (arr[r][c] == 2) chicken.push_back({r, c}); // 치킨집
+        }
+    }
+
+    // 모든 치킨 집 중에서 m개의 치킨 집을 뽑는 조합 계산
+    vector<bool> binary(chicken.size());
+    fill(binary.end() - m, binary.end(), true);
+
+    // 치킨 거리의 합의 최소를 찾아 출력
+    int result = 1e9;
+
+    do {
+        vector<pair<int, int> > now;
+        for (int i = 0; i < chicken.size(); i++) {
+            if (binary[i]) {
+                int cx = chicken[i].first;
+                int cy = chicken[i].second;
+                now.push_back({cx, cy});
+            }
+        }
+        result = min(result, getSum(now));
+    } while(next_permutation(binary.begin(), binary.end()));
+
+    cout << result << '\n';
+}
\ No newline at end of file
diff --git a/12/7.java b/12/7.java
new file mode 100644
index 0000000..4bebfae
--- /dev/null
+++ b/12/7.java
@@ -0,0 +1,107 @@
+import java.util.*;
+
+class Combination {
+    private int n;
+    private int r;
+    private int[] now; // 현재 조합
+    private ArrayList<ArrayList<Position>> result; // 모든 조합
+
+    public ArrayList<ArrayList<Position>> getResult() {
+        return result;
+    }
+
+    public Combination(int n, int r) {
+        this.n = n;
+        this.r = r;
+        this.now = new int[r];
+        this.result = new ArrayList<ArrayList<Position>>();
+    }
+
+    public void combination(ArrayList<Position> arr, int depth, int index, int target) {
+        if (depth == r) {
+            ArrayList<Position> temp = new ArrayList<>();
+            for (int i = 0; i < now.length; i++) {
+                temp.add(arr.get(now[i]));
+            }
+            result.add(temp);
+            return;
+        }
+        if (target == n) return;
+        now[index] = target;
+        combination(arr, depth + 1, index + 1, target + 1);
+        combination(arr, depth, index, target + 1);
+    }
+}
+
+class Position {
+    private int x;
+    private int y;
+
+    public Position(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public int getX() {
+        return this.x;
+    }
+
+    public int getY() {
+        return this.y;
+    }
+}
+
+public class Main {
+
+    public static int n, m;
+    public static int[][] arr = new int[50][50];
+    public static ArrayList<Position> chicken = new ArrayList<>();
+    public static ArrayList<Position> house = new ArrayList<>();
+
+    public static int getSum(ArrayList<Position> candidates) {
+        int result = 0;
+          // 모든 집에 대하여
+          for (int i = 0; i < house.size(); i++) {
+              int hx = house.get(i).getX();
+              int hy = house.get(i).getY();
+              // 가장 가까운 치킨 집을 찾기
+              int temp = (int) 1e9;
+              for (int j = 0; j < candidates.size(); j++) {
+                  int cx = candidates.get(j).getX();
+                  int cy = candidates.get(j).getY();
+                  temp = Math.min(temp, Math.abs(hx - cx) + Math.abs(hy - cy));
+              }
+              // 가장 가까운 치킨 집까지의 거리를 더하기
+              result += temp;
+          }
+          // 치킨 거리의 합 반환
+          return result;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        for (int r = 0; r < n; r++) {
+            for (int c = 0; c < n; c++) {
+                arr[r][c] = sc.nextInt();
+                if (arr[r][c] == 1) house.add(new Position(r, c)); // 일반 집
+                else if (arr[r][c] == 2) chicken.add(new Position(r, c)); // 치킨집
+            }
+        }
+
+        // 모든 치킨 집 중에서 m개의 치킨 집을 뽑는 조합 계산
+        Combination comb = new Combination(chicken.size(), m);
+        comb.combination(chicken, 0, 0, 0);
+        ArrayList<ArrayList<Position>> chickenList = comb.getResult();
+
+        // 치킨 거리의 합의 최소를 찾아 출력
+        int result = (int) 1e9;
+        for (int i = 0; i < chickenList.size(); i++) {
+            result = Math.min(result, getSum(chickenList.get(i)));
+        }
+        System.out.println(result);
+    }
+}
diff --git a/12/7.py b/12/7.py
index 5eab061..7c29b91 100644
--- a/12/7.py
+++ b/12/7.py
@@ -32,4 +32,5 @@ def get_sum(candidate):
 result = 1e9
 for candidate in candidates:
     result = min(result, get_sum(candidate))
+
 print(result)
diff --git a/12/8.cpp b/12/8.cpp
new file mode 100644
index 0000000..c5aefa7
--- /dev/null
+++ b/12/8.cpp
@@ -0,0 +1,38 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int solution(int n, vector<int> weak, vector<int> dist) {
+    // 길이를 2배로 늘려서 '원형'을 일자 형태로 변경
+    int length = weak.size();
+    for (int i = 0; i < length; i++) {
+        weak.push_back(weak[i] + n);
+    }
+    // 투입할 친구 수의 최솟값을 찾아야 하므로 len(dist) + 1로 초기화
+    int answer = dist.size() + 1;
+    // 0부터 length - 1까지의 위치를 각각 시작점으로 설정
+    for (int start = 0; start < length; start++) {
+        // 친구를 나열하는 모든 경우 각각에 대하여 확인
+        do {
+            int cnt = 1; // 투입할 친구의 수
+            // 해당 친구가 점검할 수 있는 마지막 위치
+            int position = weak[start] + dist[cnt - 1];
+            // 시작점부터 모든 취약한 지점을 확인
+            for (int index = start; index < start + length; index++) {
+                // 점검할 수 있는 위치를 벗어나는 경우
+                if (position < weak[index]) {
+                    cnt += 1; // 새로운 친구를 투입
+                    if (cnt > dist.size()) { // 더 투입이 불가능하다면 종료
+                        break;
+                    }
+                    position = weak[index] + dist[cnt - 1];
+                }
+            }
+            answer = min(answer, cnt); // 최솟값 계산
+        } while(next_permutation(dist.begin(), dist.end()));
+    }
+    if (answer > dist.size()) {
+        return -1;
+    }
+    return answer;
+}
\ No newline at end of file
diff --git a/12/8.java b/12/8.java
new file mode 100644
index 0000000..86ce49b
--- /dev/null
+++ b/12/8.java
@@ -0,0 +1,87 @@
+import java.util.*;
+
+class Permutation {
+    private int n;
+    private int r;
+    private int[] now; // 현재 순열
+    private ArrayList<ArrayList<Integer>> result; // 모든 순열
+
+    public ArrayList<ArrayList<Integer>> getResult() {
+        return result;
+    }
+
+    public Permutation(int n, int r) {
+        this.n = n;
+        this.r = r;
+        this.now = new int[r];
+        this.result = new ArrayList<ArrayList<Integer>>();
+    }
+
+    public void swap(int[] arr, int i, int j) {
+        int temp = arr[i];
+        arr[i] = arr[j];
+        arr[j] = temp;
+    }
+
+    public void permutation(int[] arr, int depth) {
+        // 현재 순열의 길이가 r일 때 결과 저장
+        if (depth == r) {
+            ArrayList<Integer> temp = new ArrayList<>();
+            for (int i = 0; i < now.length; i++) {
+                temp.add(now[i]);
+            }
+            result.add(temp);
+            return;
+        }
+        for (int i = depth; i < n; i++) {
+            swap(arr, i, depth);
+            now[depth] = arr[depth];
+            permutation(arr, depth + 1);
+            swap(arr, i, depth);
+        }
+    }
+}
+
+class Solution {
+    public int solution(int n, int[] weak, int[] dist) {
+        // 길이를 2배로 늘려서 '원형'을 일자 형태로 변경
+        ArrayList<Integer> weakList = new ArrayList<Integer>();
+        for (int i = 0; i < weak.length; i++) {
+            weakList.add(weak[i]);
+        }
+        for (int i = 0; i < weak.length; i++) {
+            weakList.add(weak[i] + n);
+        }
+        // 투입할 친구 수의 최솟값을 찾아야 하므로 len(dist) + 1로 초기화
+        int answer = dist.length + 1;
+        // 친구 정보를 이용해 모든 순열 계산
+        Permutation perm = new Permutation(dist.length, dist.length);
+        perm.permutation(dist, 0);
+        ArrayList<ArrayList<Integer>> distList = perm.getResult();
+        // 0부터 length - 1까지의 위치를 각각 시작점으로 설정
+        for (int start = 0; start < weak.length; start++) {
+            // 친구를 나열하는 모든 경우 각각에 대하여 확인
+            for (int i = 0; i < distList.size(); i++) {
+                int cnt = 1; // 투입할 친구의 수
+                // 해당 친구가 점검할 수 있는 마지막 위치
+                int position = weakList.get(start) + distList.get(i).get(cnt - 1);
+                // 시작점부터 모든 취약한 지점을 확인
+                for (int index = start; index < start + weak.length; index++) {
+                    // 점검할 수 있는 위치를 벗어나는 경우
+                    if (position < weakList.get(index)) {
+                        cnt += 1; // 새로운 친구를 투입
+                        if (cnt > dist.length) { // 더 투입이 불가능하다면 종료
+                            break;
+                        }
+                        position = weakList.get(index) + distList.get(i).get(cnt - 1);
+                    }
+                }
+                answer = Math.min(answer, cnt); // 최솟값 계산
+            }
+        }
+        if (answer > dist.length) {
+            return -1;
+        }
+        return answer;
+    }
+}
diff --git a/12/8.py b/12/8.py
index b317c42..ae408bd 100644
--- a/12/8.py
+++ b/12/8.py
@@ -1,7 +1,7 @@
 from itertools import permutations
 
 def solution(n, weak, dist):
-    # 길이를 2배로 늘려서 '원형'을 일자 형태로 변형하기
+    # 길이를 2배로 늘려서 '원형'을 일자 형태로 변형
     length = len(weak)
     for i in range(length):
         weak.append(weak[i] + n)
diff --git a/13/1.cpp b/13/1.cpp
new file mode 100644
index 0000000..ecf0aba
--- /dev/null
+++ b/13/1.cpp
@@ -0,0 +1,53 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 도시의 개수, 도로의 개수, 거리 정보, 출발 도시 번호
+int n, m, k, x;
+vector<int> graph[300001];
+// 모든 도시에 대한 최단 거리 초기화
+vector<int> d(300001, -1);
+
+int main(void) {
+    cin >> n >> m >> k >> x;
+
+    // 모든 도로 정보 입력 받기
+    for (int i = 0; i < m; i++) {
+        int a, b;
+        cin >> a >> b;
+        graph[a].push_back(b);
+    }
+
+    // 출발 도시까지의 거리는 0으로 설정
+    d[x] = 0;
+
+    // 너비 우선 탐색(BFS) 수행
+    queue<int> q;
+    q.push(x);
+    while (!q.empty()) {
+        int now = q.front();
+        q.pop();
+        // 현재 도시에서 이동할 수 있는 모든 도시를 확인
+        for (int i = 0; i < graph[now].size(); i++) {
+            int nextNode = graph[now][i];
+            // 아직 방문하지 않은 도시라면
+            if (d[nextNode] == -1) {
+                // 최단 거리 갱신
+                d[nextNode] = d[now] + 1;
+                q.push(nextNode);
+            }
+        }
+    }
+
+    // 최단 거리가 K인 모든 도시의 번호를 오름차순으로 출력
+    bool check = false;
+    for (int i = 1; i <= n; i++) {
+        if (d[i] == k) {
+            cout << i << '\n';
+            check = true;
+        }
+    }
+
+    // 만약 최단 거리가 K인 도시가 없다면, -1 출력
+    if (!check) cout << -1 << '\n';
+}
\ No newline at end of file
diff --git a/13/1.java b/13/1.java
new file mode 100644
index 0000000..a3dd2a7
--- /dev/null
+++ b/13/1.java
@@ -0,0 +1,64 @@
+import java.util.*;
+
+public class Main {
+
+    // 도시의 개수, 도로의 개수, 거리 정보, 출발 도시 번호
+    public static int n, m, k, x;
+    public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
+    // 모든 도시에 대한 최단 거리 초기화
+    public static int[] d = new int[300001];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+        k = sc.nextInt();
+        x = sc.nextInt();
+
+        // 그래피 및 최단 거리 테이블 초기화
+        for (int i = 0; i <= n; i++) {
+            graph.add(new ArrayList<Integer>());
+            d[i] = -1;
+        }
+
+        // 모든 도로 정보 입력 받기
+        for (int i = 0; i < m; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            graph.get(a).add(b);
+        }
+
+        // 출발 도시까지의 거리는 0으로 설정
+        d[x] = 0;
+
+        // 너비 우선 탐색(BFS) 수행
+        Queue<Integer> q = new LinkedList<Integer>();
+        q.offer(x);
+        while (!q.isEmpty()) {
+            int now = q.poll();
+            // 현재 도시에서 이동할 수 있는 모든 도시를 확인
+            for (int i = 0; i < graph.get(now).size(); i++) {
+                int nextNode = graph.get(now).get(i);
+                // 아직 방문하지 않은 도시라면
+                if (d[nextNode] == -1) {
+                    // 최단 거리 갱신
+                    d[nextNode] = d[now] + 1;
+                    q.offer(nextNode);
+                }
+            }
+        }
+
+        // 최단 거리가 K인 모든 도시의 번호를 오름차순으로 출력
+        boolean check = false;
+        for (int i = 1; i <= n; i++) {
+            if (d[i] == k) {
+                System.out.println(i);
+                check = true;
+            }
+        }
+
+        // 만약 최단 거리가 K인 도시가 없다면, -1 출력
+        if (!check) System.out.println(-1);
+    }
+}
\ No newline at end of file
diff --git a/13/1.py b/13/1.py
index ce0ddc8..ad11e2b 100644
--- a/13/1.py
+++ b/13/1.py
@@ -2,23 +2,23 @@
 
 # 도시의 개수, 도로의 개수, 거리 정보, 출발 도시 번호
 n, m, k, x = map(int, input().split())
-adj = [[] for _ in range(n + 1)]
+graph = [[] for _ in range(n + 1)]
 
 # 모든 도로 정보 입력 받기
 for _ in range(m):
     a, b = map(int, input().split())
-    adj[a].append(b)
+    graph[a].append(b)
 
-# 모든 노드에 대한 최단 거리 초기화
+# 모든 도시에 대한 최단 거리 초기화
 distance = [-1] * (n + 1)
 distance[x] = 0 # 출발 도시까지의 거리는 0으로 설정
 
-# BFS 수행
+# 너비 우선 탐색(BFS) 수행
 q = deque([x])
 while q:
     now = q.popleft()
-    # 이동할 수 있는 모든 도시를 확인
-    for next_node in adj[now]:
+    # 현재 도시에서 이동할 수 있는 모든 도시를 확인
+    for next_node in graph[now]:
         # 아직 방문하지 않은 도시라면
         if distance[next_node] == -1:
             # 최단 거리 갱신
diff --git a/13/2.cpp b/13/2.cpp
new file mode 100644
index 0000000..31f147d
--- /dev/null
+++ b/13/2.cpp
@@ -0,0 +1,90 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, m;
+int arr[8][8]; // 초기 맵 배열
+int temp[8][8]; // 벽을 설치한 뒤의 맵 배열
+
+// 4가지 이동 방향에 대한 배열
+int dx[] = {-1, 0, 1, 0};
+int dy[] = {0, 1, 0, -1};
+
+int result;
+
+// 깊이 우선 탐색(DFS)을 이용해 각 바이러스가 사방으로 퍼지도록 하기
+void virus(int x, int y) {
+    for (int i = 0; i < 4; i++) {
+        int nx = x + dx[i];
+        int ny = y + dy[i];
+        // 상, 하, 좌, 우 중에서 바이러스가 퍼질 수 있는 경우
+        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
+            if (temp[nx][ny] == 0) {
+                // 해당 위치에 바이러스 배치하고, 다시 재귀적으로 수행
+                temp[nx][ny] = 2;
+                virus(nx, ny);
+            }
+        }
+    }
+}
+
+// 현재 맵에서 안전 영역의 크기 계산하는 메서드
+int getScore() {
+    int score = 0;
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < m; j++) {
+            if (temp[i][j] == 0) {
+                score += 1;
+            }
+        }
+    }
+    return score;
+}
+
+// 깊이 우선 탐색(DFS)을 이용해 울타리를 설치하면서, 매 번 안전 영역의 크기 계산
+void dfs(int count) {
+    // 울타리가 3개 설치된 경우
+    if (count == 3) {
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                temp[i][j] = arr[i][j];
+            }
+        }
+        // 각 바이러스의 위치에서 전파 진행
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                if (temp[i][j] == 2) {
+                    virus(i, j);
+                }
+            }
+        }
+        // 안전 영역의 최대값 계산
+        result = max(result, getScore());
+        return;
+    }
+    // 빈 공간에 울타리를 설치
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < m; j++) {
+            if (arr[i][j] == 0) {
+                arr[i][j] = 1;
+                count += 1;
+                dfs(count);
+                arr[i][j] = 0;
+                count -= 1;
+            }
+        }
+    }
+}
+
+int main(void) {
+    cin >> n >> m;
+
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < m; j++) {
+            cin >> arr[i][j];
+        }
+    }
+
+    dfs(0);
+    cout << result << '\n';
+}
\ No newline at end of file
diff --git a/13/2.java b/13/2.java
new file mode 100644
index 0000000..f6c1d25
--- /dev/null
+++ b/13/2.java
@@ -0,0 +1,92 @@
+import java.util.*;
+
+public class Main {
+
+    public static int n, m, result = 0;
+    public static int[][] arr = new int[8][8]; // 초기 맵 배열
+    public static int[][] temp = new int[8][8]; // 벽을 설치한 뒤의 맵 배열
+    
+    // 4가지 이동 방향에 대한 배열
+    public static int[] dx = {-1, 0, 1, 0};
+    public static int[] dy = {0, 1, 0, -1};
+
+    // 깊이 우선 탐색(DFS)을 이용해 각 바이러스가 사방으로 퍼지도록 하기
+    public static void virus(int x, int y) {
+        for (int i = 0; i < 4; i++) {
+            int nx = x + dx[i];
+            int ny = y + dy[i];
+            // 상, 하, 좌, 우 중에서 바이러스가 퍼질 수 있는 경우
+            if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
+                if (temp[nx][ny] == 0) {
+                    // 해당 위치에 바이러스 배치하고, 다시 재귀적으로 수행
+                    temp[nx][ny] = 2;
+                    virus(nx, ny);
+                }
+            }
+        }
+    }
+
+    // 현재 맵에서 안전 영역의 크기 계산하는 메서드
+    public static int getScore() {
+        int score = 0;
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                if (temp[i][j] == 0) {
+                    score += 1;
+                }
+            }
+        }
+        return score;
+    }
+
+    // 깊이 우선 탐색(DFS)을 이용해 울타리를 설치하면서, 매 번 안전 영역의 크기 계산
+    public static void dfs(int count) {
+        // 울타리가 3개 설치된 경우
+        if (count == 3) {
+            for (int i = 0; i < n; i++) {
+                for (int j = 0; j < m; j++) {
+                    temp[i][j] = arr[i][j];
+                }
+            }
+            // 각 바이러스의 위치에서 전파 진행
+            for (int i = 0; i < n; i++) {
+                for (int j = 0; j < m; j++) {
+                    if (temp[i][j] == 2) {
+                        virus(i, j);
+                    }
+                }
+            }
+            // 안전 영역의 최대값 계산
+            result = Math.max(result, getScore());
+            return;
+        }
+        // 빈 공간에 울타리를 설치
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                if (arr[i][j] == 0) {
+                    arr[i][j] = 1;
+                    count += 1;
+                    dfs(count);
+                    arr[i][j] = 0;
+                    count -= 1;
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                arr[i][j] = sc.nextInt();
+            }
+        }
+
+        dfs(0);
+        System.out.println(result);
+    }
+}
\ No newline at end of file
diff --git a/13/2.py b/13/2.py
index 5abf0b7..6ad7899 100644
--- a/13/2.py
+++ b/13/2.py
@@ -1,3 +1,5 @@
+# BOJ에서는 [언어]를 PyPy3로 설정하여 제출해주세요.
+
 n, m = map(int, input().split())
 data = [] # 초기 맵 리스트
 temp = [[0] * m for _ in range(n)] # 벽을 설치한 뒤의 맵 리스트
@@ -11,7 +13,7 @@
 
 result = 0
 
-# 각 바이러스가 사방으로 퍼짐
+# 깊이 우선 탐색(DFS)을 이용해 각 바이러스가 사방으로 퍼지도록 하기
 def virus(x, y):
     for i in range(4):
         nx = x + dx[i]
@@ -23,7 +25,7 @@ def virus(x, y):
                 temp[nx][ny] = 2
                 virus(nx, ny)
 
-# 현재 맵에서 안전 영역의 크기 계산
+# 현재 맵에서 안전 영역의 크기 계산하는 메서드
 def get_score():
     score = 0
     for i in range(n):
@@ -32,7 +34,7 @@ def get_score():
                 score += 1
     return score
 
-# 재귀적으로 울타리를 설치하면서, 안전 영역의 크기 계산
+# 깊이 우선 탐색(DFS)을 이용해 울타리를 설치하면서, 매 번 안전 영역의 크기 계산
 def dfs(count):
     global result
     # 울타리가 3개 설치된 경우
@@ -48,7 +50,7 @@ def dfs(count):
         # 안전 영역의 최대값 계산
         result = max(result, get_score())
         return
-    # 빈 공간에 울타리를 설치합니다.
+    # 빈 공간에 울타리를 설치
     for i in range(n):
         for j in range(m):
             if data[i][j] == 0:
diff --git a/13/3.cpp b/13/3.cpp
new file mode 100644
index 0000000..c245d03
--- /dev/null
+++ b/13/3.cpp
@@ -0,0 +1,80 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+class Virus {
+public:
+    int index;
+    int second;
+    int x;
+    int y;
+    Virus(int index, int second, int x, int y) {
+        this->index = index;
+        this->second = second;
+        this->x = x;
+        this->y = y;
+    }
+    // 정렬 기준은 '번호가 낮은 순서'
+    bool operator <(Virus &other) {
+        return this->index < other.index; 
+    }
+};
+
+int n, k;
+// 전체 보드 정보를 담는 배열
+int graph[200][200];
+// 바이러스에 대한 정보를 담는 리스트
+vector<Virus> viruses;
+
+// 바이러스가 퍼져나갈 수 있는 4가지의 위치
+int dx[] = {-1, 0, 1, 0};
+int dy[] = {0, 1, 0, -1};
+
+int main(void) {
+    cin >> n >> k;
+
+    // 보드 정보를 한 줄 단위로 입력
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < n; j++) {
+            cin >> graph[i][j];
+            // 해당 위치에 바이러스가 존재하는 경우
+            if (graph[i][j] != 0) {
+                // (바이러스 종류, 시간, 위치 X, 위치 Y) 삽입
+                viruses.push_back(Virus(graph[i][j], 0, i, j));
+            }
+        }
+    }
+
+    // 정렬 이후에 큐로 옮기기 (낮은 번호의 바이러스가 먼저 증식하므로)
+    sort(viruses.begin(), viruses.end());
+    queue<Virus> q;
+    for (int i = 0; i < viruses.size(); i++) {
+        q.push(viruses[i]);
+    }
+
+    int target_s, target_x, target_y;
+    cin >> target_s >> target_x >> target_y;
+    
+    // 너비 우선 탐색(BFS) 진행
+    while (!q.empty()) {
+        Virus virus = q.front();
+        q.pop();
+        // 정확히 second만큼 초가 지나거나, 큐가 빌 때까지 반복
+        if (virus.second == target_s) break;
+        // 현재 노드에서 주변 4가지 위치를 각각 확인
+        for (int i = 0; i < 4; i++) {
+            int nx = virus.x + dx[i];
+            int ny = virus.y + dy[i];
+            // 해당 위치로 이동할 수 있는 경우
+            if (0 <= nx && nx < n && 0 <= ny && ny < n) {
+                // 아직 방문하지 않은 위치라면, 그 위치에 바이러스 넣기
+                if (graph[nx][ny] == 0) {
+                    graph[nx][ny] = virus.index;
+                    q.push(Virus(virus.index, virus.second + 1, nx, ny));
+                }
+            }
+        }
+    }
+
+    cout << graph[target_x - 1][target_y - 1] << '\n';
+}
\ No newline at end of file
diff --git a/13/3.java b/13/3.java
new file mode 100644
index 0000000..b581d0b
--- /dev/null
+++ b/13/3.java
@@ -0,0 +1,104 @@
+import java.util.*;
+
+class Virus implements Comparable<Virus> {
+
+    private int index;
+    private int second;
+    private int x;
+    private int y;
+
+    public Virus(int index, int second, int x, int y) {
+        this.index = index;
+        this.second = second;
+        this.x = x;
+        this.y = y;
+    }
+
+    public int getIndex() {
+        return this.index;
+    }
+
+    public int getSecond() {
+        return this.second;
+    }
+
+    public int getX() {
+        return this.x;
+    }
+
+    public int getY() {
+        return this.y;
+    }
+
+    // 정렬 기준은 '번호가 낮은 순서'
+    @Override
+    public int compareTo(Virus other) {
+        if (this.index < other.index) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+
+    public static int n, k;
+    // 전체 보드 정보를 담는 배열
+    public static int[][] graph = new int[200][200];
+    public static ArrayList<Virus> viruses = new ArrayList<Virus>();
+    
+    // 바이러스가 퍼져나갈 수 있는 4가지의 위치
+    public static int[] dx = {-1, 0, 1, 0};
+    public static int[] dy = {0, 1, 0, -1};
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        k = sc.nextInt();
+
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                graph[i][j] = sc.nextInt();
+                // 해당 위치에 바이러스가 존재하는 경우
+                if (graph[i][j] != 0) {
+                    // (바이러스 종류, 시간, 위치 X, 위치 Y) 삽입
+                    viruses.add(new Virus(graph[i][j], 0, i, j));
+                }
+            }
+        }
+
+        // 정렬 이후에 큐로 옮기기 (낮은 번호의 바이러스가 먼저 증식하므로)
+        Collections.sort(viruses);
+        Queue<Virus> q = new LinkedList<Virus>();
+        for (int i = 0; i < viruses.size(); i++) {
+            q.offer(viruses.get(i));
+        }
+
+        int targetS = sc.nextInt();
+        int targetX = sc.nextInt();
+        int targetY = sc.nextInt();
+
+        // 너비 우선 탐색(BFS) 진행
+        while (!q.isEmpty()) {
+            Virus virus = q.poll();
+            // 정확히 second만큼 초가 지나거나, 큐가 빌 때까지 반복
+            if (virus.getSecond() == targetS) break;
+            // 현재 노드에서 주변 4가지 위치를 각각 확인
+            for (int i = 0; i < 4; i++) {
+                int nx = virus.getX() + dx[i];
+                int ny = virus.getY() + dy[i];
+                // 해당 위치로 이동할 수 있는 경우
+                if (0 <= nx && nx < n && 0 <= ny && ny < n) {
+                    // 아직 방문하지 않은 위치라면, 그 위치에 바이러스 넣기
+                    if (graph[nx][ny] == 0) {
+                        graph[nx][ny] = virus.getIndex();
+                        q.offer(new Virus(virus.getIndex(), virus.getSecond() + 1, nx, ny));
+                    }
+                }
+            }
+        }
+
+        System.out.println(graph[targetX - 1][targetY - 1]);
+    }
+}
diff --git a/13/3.py b/13/3.py
index ce125b1..c21d0f2 100644
--- a/13/3.py
+++ b/13/3.py
@@ -2,19 +2,19 @@
 
 n, k = map(int, input().split())
 
-board = [] # 전체 보드 정보를 담는 리스트
+graph = [] # 전체 보드 정보를 담는 리스트
 data = [] # 바이러스에 대한 정보를 담는 리스트
 
 for i in range(n):
     # 보드 정보를 한 줄 단위로 입력
-    board.append(list(map(int, input().split())))
+    graph.append(list(map(int, input().split())))
     for j in range(n):
         # 해당 위치에 바이러스가 존재하는 경우
-        if board[i][j] != 0:
+        if graph[i][j] != 0:
             # (바이러스 종류, 시간, 위치 X, 위치 Y) 삽입
-            data.append((board[i][j], 0, i, j))
+            data.append((graph[i][j], 0, i, j))
 
-# 정렬 이후에 큐로 옮기기
+# 정렬 이후에 큐로 옮기기 (낮은 번호의 바이러스가 먼저 증식하므로)
 data.sort()
 q = deque(data)
  
@@ -23,21 +23,22 @@
 # 바이러스가 퍼져나갈 수 있는 4가지의 위치
 dx = [-1, 0, 1, 0]
 dy = [0, 1, 0, -1]
- 
+
+# 너비 우선 탐색(BFS) 진행
 while q:
     virus, s, x, y = q.popleft()
     # 정확히 s초가 지나거나, 큐가 빌 때까지 반복
     if s == target_s:
         break
-    # 4가지 위치를 각각 확인
+    # 현재 노드에서 주변 4가지 위치를 각각 확인
     for i in range(4):
         nx = x + dx[i]
         ny = y + dy[i]
         # 해당 위치로 이동할 수 있는 경우
         if 0 <= nx and nx < n and 0 <= ny and ny < n:
             # 아직 방문하지 않은 위치라면, 그 위치에 바이러스 넣기
-            if board[nx][ny] == 0:
-                board[nx][ny] = virus
+            if graph[nx][ny] == 0:
+                graph[nx][ny] = virus
                 q.append((virus, s + 1, nx, ny))
 
-print(board[target_x - 1][target_y - 1])
+print(graph[target_x - 1][target_y - 1])
diff --git a/13/4.cpp b/13/4.cpp
new file mode 100644
index 0000000..8bbe1c4
--- /dev/null
+++ b/13/4.cpp
@@ -0,0 +1,54 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// "균형잡힌 괄호 문자열"의 인덱스 반환
+int balancedIndex(string p) {
+    int count = 0; // 왼쪽 괄호의 개수
+    for (int i = 0; i < p.size(); i++) {
+        if (p[i] == '(') count += 1;
+        else count -= 1;
+        if (count == 0) return i;
+    }
+    return -1;
+}
+
+// "올바른 괄호 문자열"인지 판단
+bool checkProper(string p) {
+    int count = 0; // 왼쪽 괄호의 개수
+    for (int i = 0; i < p.size(); i++) {
+        if (p[i] == '(') count += 1;
+        else {
+            if (count == 0) { // 쌍이 맞지 않는 경우에 false 반환
+                return false;
+            }
+            count -= 1;
+        }
+    }
+    return true; // 쌍이 맞는 경우에 true 반환
+}
+
+string solution(string p) {
+    string answer = "";
+    if (p == "") return answer;
+    int index = balancedIndex(p);
+    string u = p.substr(0, index + 1);
+    string v = p.substr(index + 1);
+    // "올바른 괄호 문자열"이면, v에 대해 함수를 수행한 결과를 붙여 반환
+    if (checkProper(u)) {
+        answer = u + solution(v);
+    }
+    // "올바른 괄호 문자열"이 아니라면 아래의 과정을 수행
+    else {
+        answer = "(";
+        answer += solution(v);
+        answer += ")";
+        u = u.substr(1, u.size() - 2); // 첫 번째와 마지막 문자를 제거
+        for (int i = 0; i < u.size(); i++) {
+            if (u[i] == '(') u[i] = ')';
+            else u[i] = '(';
+        }
+        answer += u;
+    }
+    return answer;
+}
\ No newline at end of file
diff --git a/13/4.java b/13/4.java
new file mode 100644
index 0000000..9e1e854
--- /dev/null
+++ b/13/4.java
@@ -0,0 +1,56 @@
+import java.util.*;
+
+class Solution {
+    
+    // "균형잡힌 괄호 문자열"의 인덱스 반환
+    public int balancedIndex(String p) {
+        int count = 0; // 왼쪽 괄호의 개수
+        for (int i = 0; i < p.length(); i++) {
+            if (p.charAt(i) == '(') count += 1;
+            else count -= 1;
+            if (count == 0) return i;
+        }
+        return -1;
+    }
+
+    // "올바른 괄호 문자열"인지 판단
+    public boolean checkProper(String p) {
+        int count = 0; // 왼쪽 괄호의 개수
+        for (int i = 0; i < p.length(); i++) {
+            if (p.charAt(i) == '(') count += 1;
+            else {
+                if (count == 0) { // 쌍이 맞지 않는 경우에 false 반환
+                    return false;
+                }
+                count -= 1;
+            }
+        }
+        return true; // 쌍이 맞는 경우에 true 반환
+    }
+    
+    public String solution(String p) {
+        String answer = "";
+        if (p.equals("")) return answer;
+        int index = balancedIndex(p);
+        String u = p.substring(0, index + 1);
+        String v = p.substring(index + 1);
+        // "올바른 괄호 문자열"이면, v에 대해 함수를 수행한 결과를 붙여 반환
+        if (checkProper(u)) {
+            answer = u + solution(v);
+        }
+        // "올바른 괄호 문자열"이 아니라면 아래의 과정을 수행
+        else {
+            answer = "(";
+            answer += solution(v);
+            answer += ")";
+            u = u.substring(1, u.length() - 1); // 첫 번째와 마지막 문자를 제거
+            String temp = "";
+            for (int i = 0; i < u.length(); i++) {
+                if (u.charAt(i) == '(') temp += ")";
+                else temp += "(";
+            }
+            answer += temp;
+        }
+        return answer;
+    }
+}
diff --git a/13/4.py b/13/4.py
index dd2f770..a1e448a 100644
--- a/13/4.py
+++ b/13/4.py
@@ -16,10 +16,10 @@ def check_proper(p):
         if i == '(':
             count += 1
         else:
-            if count == 0: # 쌍이 안 맞으면
+            if count == 0: # 쌍이 맞지 않는 경우에 False 반환
                 return False
             count -= 1
-    return True
+    return True # 쌍이 맞는 경우에 True 반환
 
 def solution(p):
     answer = ''
diff --git a/13/5.cpp b/13/5.cpp
new file mode 100644
index 0000000..1aa5a60
--- /dev/null
+++ b/13/5.cpp
@@ -0,0 +1,61 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n;
+// 연산을 수행하고자 하는 수 리스트
+vector<int> arr;
+// 더하기, 빼기, 곱하기, 나누기 연산자 개수
+int add, sub, mul, divi;
+
+// 최솟값과 최댓값 초기화
+int minValue = 1e9;
+int maxValue = -1e9;
+
+// 깊이 우선 탐색 (DFS) 메서드
+void dfs(int i, int now) {
+    // 모든 연산자를 다 사용한 경우, 최솟값과 최댓값 업데이트
+    if (i == n) {
+        minValue = min(minValue, now);
+        maxValue = max(maxValue, now);
+    }
+    else {
+        // 각 연산자에 대하여 재귀적으로 수행
+        if (add > 0) {
+            add -= 1;
+            dfs(i + 1, now + arr[i]);
+            add += 1;
+        }
+        if (sub > 0) {
+            sub -= 1;
+            dfs(i + 1, now - arr[i]);
+            sub += 1;
+        }
+        if (mul > 0) {
+            mul -= 1;
+            dfs(i + 1, now * arr[i]);
+            mul += 1;
+        }
+        if (divi > 0) {
+            divi -= 1;
+            dfs(i + 1, now / arr[i]);
+            divi += 1;
+        }
+    }
+}
+
+int main(void) {
+    cin >> n;
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+    cin >> add >> sub >> mul >> divi;
+
+    // DFS 메서드 호출
+    dfs(1, arr[0]);
+
+    // 최댓값과 최솟값 차례대로 출력
+    cout << maxValue << '\n' << minValue << '\n';
+}
\ No newline at end of file
diff --git a/13/5.java b/13/5.java
new file mode 100644
index 0000000..8956ba9
--- /dev/null
+++ b/13/5.java
@@ -0,0 +1,69 @@
+import java.util.*;
+
+public class Main {
+
+    public static int n;
+    // 연산을 수행하고자 하는 수 리스트
+    public static ArrayList<Integer> arr = new ArrayList<>();
+    // 더하기, 빼기, 곱하기, 나누기 연산자 개수
+    public static int add, sub, mul, divi;
+    
+    // 최솟값과 최댓값 초기화
+    public static int minValue = (int) 1e9;
+    public static int maxValue = (int) -1e9;
+
+    // 깊이 우선 탐색 (DFS) 메서드
+    public static void dfs(int i, int now) {
+        // 모든 연산자를 다 사용한 경우, 최솟값과 최댓값 업데이트
+        if (i == n) {
+            minValue = Math.min(minValue, now);
+            maxValue = Math.max(maxValue, now);
+        }
+        else {
+            // 각 연산자에 대하여 재귀적으로 수행
+            if (add > 0) {
+                add -= 1;
+                dfs(i + 1, now + arr.get(i));
+                add += 1;
+            }
+            if (sub > 0) {
+                sub -= 1;
+                dfs(i + 1, now - arr.get(i));
+                sub += 1;
+            }
+            if (mul > 0) {
+                mul -= 1;
+                dfs(i + 1, now * arr.get(i));
+                mul += 1;
+            }
+            if (divi > 0) {
+                divi -= 1;
+                dfs(i + 1, now / arr.get(i));
+                divi += 1;
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+
+        for (int i = 0; i < n; i++) {
+            int x = sc.nextInt();
+            arr.add(x);
+        }
+
+        add = sc.nextInt();
+        sub = sc.nextInt();
+        mul = sc.nextInt();
+        divi = sc.nextInt();
+
+        // DFS 메서드 호출
+        dfs(1, arr.get(0));
+
+        // 최댓값과 최솟값 차례대로 출력
+        System.out.println(maxValue);
+        System.out.println(minValue);
+    }
+}
\ No newline at end of file
diff --git a/13/5.py b/13/5.py
index 995e2a2..1cedfe4 100644
--- a/13/5.py
+++ b/13/5.py
@@ -4,16 +4,19 @@
 # 더하기, 빼기, 곱하기, 나누기 연산자 개수
 add, sub, mul, div = map(int, input().split())
 
+# 최솟값과 최댓값 초기화
 min_value = 1e9
 max_value = -1e9
 
+# 깊이 우선 탐색 (DFS) 메서드
 def dfs(i, now):
     global min_value, max_value, add, sub, mul, div
+    # 모든 연산자를 다 사용한 경우, 최솟값과 최댓값 업데이트
     if i == n:
         min_value = min(min_value, now)
         max_value = max(max_value, now)
     else:
-        # 각 연산자에 대하여 DFS 수행
+        # 각 연산자에 대하여 재귀적으로 수행
         if add > 0:
             add -= 1
             dfs(i + 1, now + data[i])
@@ -31,6 +34,9 @@ def dfs(i, now):
             dfs(i + 1, int(now / data[i])) # 나눌 때는 나머지를 제거
             div += 1
 
+# DFS 메서드 호출
 dfs(1, data[0])
+
+# 최댓값과 최솟값 차례대로 출력
 print(max_value)
 print(min_value)
diff --git a/13/6.cpp b/13/6.cpp
new file mode 100644
index 0000000..484e942
--- /dev/null
+++ b/13/6.cpp
@@ -0,0 +1,128 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n; // 복도의 크기
+char board[6][6]; // 복도 정보 (N x N)
+vector<pair<int, int> > teachers; // 모든 선생님 위치 정보
+vector<pair<int, int> > spaces; // 모든 빈 공간 위치 정보
+
+// 특정 방향으로 감시를 진행 (학생 발견: true, 학생 미발견: false)
+bool watch(int x, int y, int direction) {
+    // 왼쪽 방향으로 감시
+    if (direction == 0) {
+        while (y >= 0) {
+            if (board[x][y] == 'S') { // 학생이 있는 경우
+                return true;
+            }
+            if (board[x][y] == 'O') { // 장애물이 있는 경우
+                return false;
+            }
+            y -= 1;
+        }
+    }
+    // 오른쪽 방향으로 감시
+    if (direction == 1) {
+        while (y < n) {
+            if (board[x][y] == 'S') { // 학생이 있는 경우
+                return true;
+            }
+            if (board[x][y] == 'O') { // 장애물이 있는 경우
+                return false;
+            }
+            y += 1;
+        }
+    }
+    // 위쪽 방향으로 감시
+    if (direction == 2) {
+        while (x >= 0) {
+            if (board[x][y] == 'S') { // 학생이 있는 경우
+                return true;
+            }
+            if (board[x][y] == 'O') { // 장애물이 있는 경우
+                return false;
+            }
+            x -= 1;
+        }
+    }
+    // 아래쪽 방향으로 감시
+    if (direction == 3) {
+        while (x < n) {
+            if (board[x][y] == 'S') { // 학생이 있는 경우
+                return true;
+            }
+            if (board[x][y] == 'O') { // 장애물이 있는 경우
+                return false;
+            }
+            x += 1;
+        }
+    }
+    return false;
+}
+
+// 장애물 설치 이후에, 한 명이라도 학생이 감지되는지 검사
+bool process() {
+    // 모든 선생의 위치를 하나씩 확인
+    for (int i = 0; i < teachers.size(); i++) {
+        int x = teachers[i].first;
+        int y = teachers[i].second;
+        // 4가지 방향으로 학생을 감지할 수 있는지 확인
+        for (int i = 0; i < 4; i++) {
+            if (watch(x, y, i)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool found; // 학생이 한 명도 감지되지 않도록 설치할 수 있는지의 여부
+
+int main(void) {
+    cin >> n;
+
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < n; j++) {
+            cin >> board[i][j];
+            // 선생님이 존재하는 위치 저장
+            if (board[i][j] == 'T') {
+                teachers.push_back({i, j});
+            }
+            // 장애물을 설치할 수 있는 (빈 공간) 위치 저장
+            if (board[i][j] == 'X') {
+                spaces.push_back({i, j});
+            }
+        }
+    }
+
+    // 빈 공간에서 3개를 뽑는 모든 조합을 확인
+    vector<bool> binary(spaces.size());
+    fill(binary.end() - 3, binary.end(), true);
+    do {
+        // 장애물들을 설치해보기
+        for (int i = 0; i < spaces.size(); i++) {
+            if (binary[i]) {
+                int x = spaces[i].first;
+                int y = spaces[i].second;
+                board[x][y] = 'O';
+            }
+        }
+        // 학생이 한 명도 감지되지 않는 경우
+        if (!process()) {
+            // 원하는 경우를 발견한 것임
+            found = true;
+            break;
+        }
+        // 설치된 장애물을 다시 없애기
+        for (int i = 0; i < spaces.size(); i++) {
+            if (binary[i]) {
+                int x = spaces[i].first;
+                int y = spaces[i].second;
+                board[x][y] = 'X';
+            }
+        }
+    } while(next_permutation(binary.begin(), binary.end()));
+
+    if (found) cout << "YES" << '\n';
+    else cout << "NO" << '\n';
+}
\ No newline at end of file
diff --git a/13/6.java b/13/6.java
new file mode 100644
index 0000000..4b8cdd5
--- /dev/null
+++ b/13/6.java
@@ -0,0 +1,180 @@
+import java.util.*;
+
+class Combination {
+    private int n;
+    private int r;
+    private int[] now; // 현재 조합
+    private ArrayList<ArrayList<Position>> result; // 모든 조합
+
+    public ArrayList<ArrayList<Position>> getResult() {
+        return result;
+    }
+
+    public Combination(int n, int r) {
+        this.n = n;
+        this.r = r;
+        this.now = new int[r];
+        this.result = new ArrayList<ArrayList<Position>>();
+    }
+
+    public void combination(ArrayList<Position> arr, int depth, int index, int target) {
+        if (depth == r) {
+            ArrayList<Position> temp = new ArrayList<>();
+            for (int i = 0; i < now.length; i++) {
+                temp.add(arr.get(now[i]));
+            }
+            result.add(temp);
+            return;
+        }
+        if (target == n) return;
+        now[index] = target;
+        combination(arr, depth + 1, index + 1, target + 1);
+        combination(arr, depth, index, target + 1);
+    }
+}
+
+class Position {
+    private int x;
+    private int y;
+
+    public Position(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public int getX() {
+        return this.x;
+    }
+
+    public int getY() {
+        return this.y;
+    }
+}
+
+public class Main {
+
+    public static int n; // 복도의 크기
+    public static char[][] board = new char[6][6]; // 복도 정보 (N x N)
+    public static ArrayList<Position> teachers = new ArrayList<>(); // 모든 선생님 위치 정보
+    public static ArrayList<Position> spaces = new ArrayList<>(); // 모든 빈 공간 위치 정보
+
+    // 특정 방향으로 감시를 진행 (학생 발견: true, 학생 미발견: false)
+    public static boolean watch(int x, int y, int direction) {
+        // 왼쪽 방향으로 감시
+        if (direction == 0) {
+            while (y >= 0) {
+                if (board[x][y] == 'S') { // 학생이 있는 경우
+                    return true;
+                }
+                if (board[x][y] == 'O') { // 장애물이 있는 경우
+                    return false;
+                }
+                y -= 1;
+            }
+        }
+        // 오른쪽 방향으로 감시
+        if (direction == 1) {
+            while (y < n) {
+                if (board[x][y] == 'S') { // 학생이 있는 경우
+                    return true;
+                }
+                if (board[x][y] == 'O') { // 장애물이 있는 경우
+                    return false;
+                }
+                y += 1;
+            }
+        }
+        // 위쪽 방향으로 감시
+        if (direction == 2) {
+            while (x >= 0) {
+                if (board[x][y] == 'S') { // 학생이 있는 경우
+                    return true;
+                }
+                if (board[x][y] == 'O') { // 장애물이 있는 경우
+                    return false;
+                }
+                x -= 1;
+            }
+        }
+        // 아래쪽 방향으로 감시
+        if (direction == 3) {
+            while (x < n) {
+                if (board[x][y] == 'S') { // 학생이 있는 경우
+                    return true;
+                }
+                if (board[x][y] == 'O') { // 장애물이 있는 경우
+                    return false;
+                }
+                x += 1;
+            }
+        }
+        return false;
+    }
+
+    // 장애물 설치 이후에, 한 명이라도 학생이 감지되는지 검사
+    public static boolean process() {
+        // 모든 선생의 위치를 하나씩 확인
+        for (int i = 0; i < teachers.size(); i++) {
+            int x = teachers.get(i).getX();
+            int y = teachers.get(i).getY();
+            // 4가지 방향으로 학생을 감지할 수 있는지 확인
+            for (int j = 0; j < 4; j++) {
+                if (watch(x, y, j)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                board[i][j] = sc.next().charAt(0);
+                // 선생님이 존재하는 위치 저장
+                if (board[i][j] == 'T') {
+                    teachers.add(new Position(i, j));
+                }
+                // 장애물을 설치할 수 있는 (빈 공간) 위치 저장
+                if (board[i][j] == 'X') {
+                    spaces.add(new Position(i, j));
+                }
+            }
+        }
+
+        // 빈 공간에서 3개를 뽑는 모든 조합을 확인
+        Combination comb = new Combination(spaces.size(), 3);
+        comb.combination(spaces, 0, 0, 0);
+        ArrayList<ArrayList<Position>> spaceList = comb.getResult();
+
+        // 학생이 한 명도 감지되지 않도록 설치할 수 있는지의 여부
+        boolean found = false; 
+        for (int i = 0; i < spaceList.size(); i++) {
+            // 장애물들을 설치해보기
+            for (int j = 0; j < spaceList.get(i).size(); j++) {
+                int x = spaceList.get(i).get(j).getX();
+                int y = spaceList.get(i).get(j).getY();
+                board[x][y] = 'O';
+            }
+            // 학생이 한 명도 감지되지 않는 경우
+            if (!process()) {
+                // 원하는 경우를 발견한 것임
+                found = true;
+                break;
+            }
+            // 설치된 장애물을 다시 없애기
+            for (int j = 0; j < spaceList.get(i).size(); j++) {
+                int x = spaceList.get(i).get(j).getX();
+                int y = spaceList.get(i).get(j).getY();
+                board[x][y] = 'X';
+            }
+        }
+
+        if (found) System.out.println("YES");
+        else System.out.println("NO");
+    }
+}
diff --git a/13/6.py b/13/6.py
index a0c0065..d09807d 100644
--- a/13/6.py
+++ b/13/6.py
@@ -1,17 +1,18 @@
 from itertools import combinations
 
-n = int(input())
-a = []
-teachers = []
-spaces = []
+n = int(input()) # 복도의 크기
+board = [] # 복도 정보 (N x N)
+teachers = [] # 모든 선생님 위치 정보
+spaces = [] # 모든 빈 공간 위치 정보
+
 for i in range(n):
-    a.append(list(input().split()))
+    board.append(list(input().split()))
     for j in range(n):
         # 선생님이 존재하는 위치 저장
-        if a[i][j] == 'T':
+        if board[i][j] == 'T':
             teachers.append((i, j))
-        # 장애물을 설치할 수 있는 위치 저장
-        if a[i][j] == 'X':
+        # 장애물을 설치할 수 있는 (빈 공간) 위치 저장
+        if board[i][j] == 'X':
             spaces.append((i, j))
 
 # 특정 방향으로 감시를 진행 (학생 발견: True, 학생 미발견: False)
@@ -19,33 +20,33 @@ def watch(x, y, direction):
     # 왼쪽 방향으로 감시
     if direction == 0:
         while y >= 0:
-            if a[x][y] == 'S': # 학생이 있는 경우
+            if board[x][y] == 'S': # 학생이 있는 경우
                 return True
-            if a[x][y] == 'O': # 장애물이 있는 경우
+            if board[x][y] == 'O': # 장애물이 있는 경우
                 return False
             y -= 1
     # 오른쪽 방향으로 감시
     if direction == 1:
         while y < n:
-            if a[x][y] == 'S': # 학생이 있는 경우
+            if board[x][y] == 'S': # 학생이 있는 경우
                 return True
-            if a[x][y] == 'O': # 장애물이 있는 경우
+            if board[x][y] == 'O': # 장애물이 있는 경우
                 return False
             y += 1
     # 위쪽 방향으로 감시
     if direction == 2:
         while x >= 0:
-            if a[x][y] == 'S': # 학생이 있는 경우
+            if board[x][y] == 'S': # 학생이 있는 경우
                 return True
-            if a[x][y] == 'O': # 장애물이 있는 경우
+            if board[x][y] == 'O': # 장애물이 있는 경우
                 return False
             x -= 1
     # 아래쪽 방향으로 감시
     if direction == 3:
         while x < n:
-            if a[x][y] == 'S': # 학생이 있는 경우
+            if board[x][y] == 'S': # 학생이 있는 경우
                 return True
-            if a[x][y] == 'O': # 장애물이 있는 경우
+            if board[x][y] == 'O': # 장애물이 있는 경우
                 return False
             x += 1
     return False
@@ -60,17 +61,21 @@ def process():
                 return True
     return False
 
-find = False
+find = False # 학생이 한 명도 감지되지 않도록 설치할 수 있는지의 여부
+
+# 빈 공간에서 3개를 뽑는 모든 조합을 확인
 for data in combinations(spaces, 3):
+    # 장애물들을 설치해보기
     for x, y in data:
-        a[x][y] = 'O'
+        board[x][y] = 'O'
     # 학생이 한 명도 감지되지 않는 경우
     if not process():
         # 원하는 경우를 발견한 것임
         find = True
         break
+    # 설치된 장애물을 다시 없애기
     for x, y in data:
-        a[x][y] = 'X'
+        board[x][y] = 'X'
 
 if find:
     print('YES')
diff --git a/13/7.cpp b/13/7.cpp
new file mode 100644
index 0000000..4df89b2
--- /dev/null
+++ b/13/7.cpp
@@ -0,0 +1,92 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 땅의 크기(N), L, R 값을 입력받기
+int n, l, r;
+
+// 전체 나라의 정보(N x N)를 입력받기
+int graph[50][50];
+int unions[50][50];
+
+int dx[] = {-1, 0, 1, 0};
+int dy[] = {0, -1, 0, 1};
+
+// 특정 위치에서 출발하여 모든 연합을 체크한 뒤에 데이터 갱신
+void process(int x, int y, int index) {
+    // (x, y)의 위치와 연결된 나라(연합) 정보를 담는 리스트
+    vector<pair<int, int> > united;
+    united.push_back({x, y});
+    // 너비 우선 탐색 (BFS)을 위한 큐 라이브러리 사용
+    queue<pair<int, int> > q;
+    q.push({x, y});
+    unions[x][y] = index; // 현재 연합의 번호 할당
+    int summary = graph[x][y]; // 현재 연합의 전체 인구 수
+    int count = 1; // 현재 연합의 국가 수
+    // 큐가 빌 때까지 반복(BFS)
+    while (!q.empty()) {
+        int x = q.front().first;
+        int y = q.front().second;
+        q.pop();
+        // 현재 위치에서 4가지 방향을 확인하며
+        for (int i = 0; i < 4; i++) {
+            int nx = x + dx[i];
+            int ny = y + dy[i];
+            // 바로 옆에 있는 나라를 확인하여
+            if (0 <= nx && nx < n && 0 <= ny && ny < n && unions[nx][ny] == -1) {
+                // 옆에 있는 나라와 인구 차이가 L명 이상, R명 이하라면
+                int gap = abs(graph[nx][ny] - graph[x][y]);
+                if (l <= gap && gap <= r) {
+                    q.push({nx, ny});
+                    // 연합에 추가하기
+                    unions[nx][ny] = index;
+                    summary += graph[nx][ny];
+                    count += 1;
+                    united.push_back({nx, ny});
+                }
+            }
+        }
+    }
+    // 연합 국가끼리 인구를 분배
+    for (int i = 0; i < united.size(); i++) {
+        int x = united[i].first;
+        int y = united[i].second;
+        graph[x][y] = summary / count;
+    }
+}
+
+int totalCount = 0;
+
+int main(void) {
+    cin >> n >> l >> r;
+
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < n; j++) {
+            cin >> graph[i][j];
+        }
+    }
+
+    // 더 이상 인구 이동을 할 수 없을 때까지 반복
+    while (true) {
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                unions[i][j] = -1;
+            }
+        }
+        int index = 0;
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                if (unions[i][j] == -1) { // 해당 나라가 아직 처리되지 않았다면
+                    process(i, j, index);
+                    index += 1;
+                }
+            }
+        }
+        // 모든 인구 이동이 끝난 경우
+        if (index == n * n) break;
+        totalCount += 1;
+    }
+
+    // 인구 이동 횟수 출력
+    cout << totalCount << '\n';
+}
\ No newline at end of file
diff --git a/13/7.java b/13/7.java
new file mode 100644
index 0000000..5faf2ae
--- /dev/null
+++ b/13/7.java
@@ -0,0 +1,113 @@
+import java.util.*;
+
+class Position {
+    private int x;
+    private int y;
+
+    public Position(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public int getX() {
+        return this.x;
+    }
+
+    public int getY() {
+        return this.y;
+    }
+}
+
+public class Main {
+    // 땅의 크기(N), L, R 값을 입력받기
+    public static int n, l, r;
+    public static int totalCount = 0;
+
+    // 전체 나라의 정보(N x N)를 입력받기
+    public static int[][] graph = new int[50][50];
+    public static int[][] unions = new int[50][50];
+
+    public static int[] dx = {-1, 0, 1, 0};
+    public static int[] dy = {0, -1, 0, 1};
+
+    // 특정 위치에서 출발하여 모든 연합을 체크한 뒤에 데이터 갱신
+    public static void process(int x, int y, int index) {
+        // (x, y)의 위치와 연결된 나라(연합) 정보를 담는 리스트
+        ArrayList<Position> united = new ArrayList<>();
+        united.add(new Position(x, y));
+        // 너비 우선 탐색 (BFS)을 위한 큐 라이브러리 사용
+        Queue<Position> q = new LinkedList<>();
+        q.offer(new Position(x, y));
+        unions[x][y] = index; // 현재 연합의 번호 할당
+        int summary = graph[x][y]; // 현재 연합의 전체 인구 수
+        int count = 1; // 현재 연합의 국가 수
+        // 큐가 빌 때까지 반복(BFS)
+        while (!q.isEmpty()) {
+            Position pos = q.poll();
+            x = pos.getX();
+            y = pos.getY();
+            // 현재 위치에서 4가지 방향을 확인하며
+            for (int i = 0; i < 4; i++) {
+                int nx = x + dx[i];
+                int ny = y + dy[i];
+                // 바로 옆에 있는 나라를 확인하여
+                if (0 <= nx && nx < n && 0 <= ny && ny < n && unions[nx][ny] == -1) {
+                    // 옆에 있는 나라와 인구 차이가 L명 이상, R명 이하라면
+                    int gap = Math.abs(graph[nx][ny] - graph[x][y]);
+                    if (l <= gap && gap <= r) {
+                        q.offer(new Position(nx, ny));
+                        // 연합에 추가하기
+                        unions[nx][ny] = index;
+                        summary += graph[nx][ny];
+                        count += 1;
+                        united.add(new Position(nx, ny));
+                    }
+                }
+            }
+        }
+        // 연합 국가끼리 인구를 분배
+        for (int i = 0; i < united.size(); i++) {
+            x = united.get(i).getX();
+            y = united.get(i).getY();
+            graph[x][y] = summary / count;
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        l = sc.nextInt();
+        r = sc.nextInt();
+        
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                graph[i][j] = sc.nextInt();
+            }
+        }
+
+        // 더 이상 인구 이동을 할 수 없을 때까지 반복
+        while (true) {
+            for (int i = 0; i < n; i++) {
+                for (int j = 0; j < n; j++) {
+                    unions[i][j] = -1;
+                }
+            }
+            int index = 0;
+            for (int i = 0; i < n; i++) {
+                for (int j = 0; j < n; j++) {
+                    if (unions[i][j] == -1) { // 해당 나라가 아직 처리되지 않았다면
+                        process(i, j, index);
+                        index += 1;
+                    }
+                }
+            }
+            // 모든 인구 이동이 끝난 경우
+            if (index == n * n) break;
+            totalCount += 1;
+        }
+
+        // 인구 이동 횟수 출력
+        System.out.println(totalCount);
+    }
+}
diff --git a/13/7.py b/13/7.py
index 89caa78..bf84ac7 100644
--- a/13/7.py
+++ b/13/7.py
@@ -1,44 +1,47 @@
 from collections import deque
 
+# 땅의 크기(N), L, R 값을 입력받기
 n, l, r = map(int, input().split())
-data = []
 
+# 전체 나라의 정보(N x N)를 입력 받기
+graph = []
 for _ in range(n):
-    data.append(list(map(int, input().split())))
+    graph.append(list(map(int, input().split())))
 
 dx = [-1, 0, 1, 0]
 dy = [0, -1, 0, 1]
 
-result = 0
-
 # 특정 위치에서 출발하여 모든 연합을 체크한 뒤에 데이터 갱신
 def process(x, y, index):
-    routes = []
-    routes.append((x, y))
-    # DFS를 위한 큐 자료구조 정의
+    # (x, y)의 위치와 연결된 나라(연합) 정보를 담는 리스트
+    united = []
+    united.append((x, y))
+    # 너비 우선 탐색 (BFS)을 위한 큐 라이브러리 사용
     q = deque()
     q.append((x, y))
-    union[x][y] = index
-    summary = data[x][y]
-    count = 1
+    union[x][y] = index # 현재 연합의 번호 할당
+    summary = graph[x][y] # 현재 연합의 전체 인구 수
+    count = 1 # 현재 연합의 국가 수
     # 큐가 빌 때까지 반복(BFS)
     while q:
         x, y = q.popleft()
+        # 현재 위치에서 4가지 방향을 확인하며
         for i in range(4):
             nx = x + dx[i]
             ny = y + dy[i]
-            # 바로 옆 나라와 국경선이 열린 경우
+            # 바로 옆에 있는 나라를 확인하여
             if 0 <= nx < n and 0 <= ny < n and union[nx][ny] == -1:
-                if l <= abs(data[nx][ny] - data[x][y]) <= r:
+                # 옆에 있는 나라와 인구 차이가 L명 이상, R명 이하라면
+                if l <= abs(graph[nx][ny] - graph[x][y]) <= r:
+                    q.append((nx, ny))
+                    # 연합에 추가하기
                     union[nx][ny] = index
-                    summary += data[nx][ny]
+                    summary += graph[nx][ny]
                     count += 1
-                    q.append((nx, ny))
-                    routes.append((nx, ny))
+                    united.append((nx, ny))
     # 연합 국가끼리 인구를 분배
-    for i, j in routes:
-        data[i][j] = summary // count
-    return count
+    for i, j in united:
+        graph[i][j] = summary // count
 
 total_count = 0
 
@@ -51,11 +54,10 @@ def process(x, y, index):
             if union[i][j] == -1: # 해당 나라가 아직 처리되지 않았다면
                 process(i, j, index)
                 index += 1
-
     # 모든 인구 이동이 끝난 경우
     if index == n * n:
         break
-
     total_count += 1
 
+# 인구 이동 횟수 출력
 print(total_count)
diff --git a/13/8.cpp b/13/8.cpp
new file mode 100644
index 0000000..3910883
--- /dev/null
+++ b/13/8.cpp
@@ -0,0 +1,103 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+class Node {
+public:
+    int pos1X;
+    int pos1Y;
+    int pos2X;
+    int pos2Y;
+    Node(int pos1X, int pos1Y, int pos2X, int pos2Y) {
+        this->pos1X = pos1X;
+        this->pos1Y = pos1Y;
+        this->pos2X = pos2X;
+        this->pos2Y = pos2Y;
+    }
+};
+
+vector<Node> getNextPos(Node pos, vector<vector<int> > board) {
+    vector<Node> nextPos; // 반환 결과 (이동 가능한 위치들)
+    // (상, 하, 좌, 우)로 이동하는 경우에 대해서 처리
+    int dx[] = {-1, 1, 0, 0};
+    int dy[] = {0, 0, -1, 1};
+    for (int i = 0; i < 4; i++) {
+        int pos1NextX = pos.pos1X + dx[i];
+        int pos1NextY = pos.pos1Y + dy[i];
+        int pos2NextX = pos.pos2X + dx[i];
+        int pos2NextY = pos.pos2Y + dy[i];
+        // 이동하고자 하는 두 칸이 모두 비어 있다면
+        if (board[pos1NextX][pos1NextY] == 0 && board[pos2NextX][pos2NextY] == 0) {
+            nextPos.push_back(Node(pos1NextX, pos1NextY, pos2NextX, pos2NextY));
+        }
+    }
+    // 현재 로봇이 가로로 놓여 있는 경우
+    int hor[] = {-1, 1};
+    if (pos.pos1X == pos.pos2X) {
+        for (int i = 0; i < 2; i++) { // 위쪽으로 회전하거나, 아래쪽으로 회전
+            // 위쪽 혹은 아래쪽 두 칸이 모두 비어 있다면
+            if (board[pos.pos1X + hor[i]][pos.pos1Y] == 0 && board[pos.pos2X + hor[i]][pos.pos2Y] == 0) {
+                nextPos.push_back(Node(pos.pos1X, pos.pos1Y, pos.pos1X + hor[i], pos.pos1Y));
+                nextPos.push_back(Node(pos.pos2X, pos.pos2Y, pos.pos2X + hor[i], pos.pos2Y));
+            }
+        }
+    }
+    // 현재 로봇이 세로로 놓여 있는 경우
+    int ver[] = {-1, 1};
+    if (pos.pos1Y == pos.pos2Y) {
+        for (int i = 0; i < 2; i++) { // 왼쪽으로 회전하거나, 오른쪽으로 회전
+            // 왼쪽 혹은 오른쪽 두 칸이 모두 비어 있다면
+            if (board[pos.pos1X][pos.pos1Y + ver[i]] == 0 && board[pos.pos2X][pos.pos2Y + ver[i]] == 0) {
+                nextPos.push_back(Node(pos.pos1X, pos.pos1Y, pos.pos1X, pos.pos1Y + ver[i]));
+                nextPos.push_back(Node(pos.pos2X, pos.pos2Y, pos.pos2X, pos.pos2Y + ver[i]));
+            }
+        }
+    }
+    // 현재 위치에서 이동할 수 있는 위치를 반환
+    return nextPos;
+}
+
+int solution(vector<vector<int> > board) {
+    // 맵의 외곽에 벽을 두는 형태로 맵 변형
+    int n = board.size();
+    vector<vector<int> > newBoard(n + 2, vector<int>(n + 2, 1));
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < n; j++) {
+            newBoard[i + 1][j + 1] = board[i][j];
+        }
+    }
+    // 너비 우선 탐색(BFS) 수행
+    queue<pair<Node, int> > q;
+    vector<Node> visited;
+    Node pos = Node(1, 1, 1, 2); // 시작 위치 설정
+    q.push({pos, 0}); // 큐에 삽입한 뒤에
+    visited.push_back(pos); // 방문 처리
+    // 큐가 빌 때까지 반복
+    while (!q.empty()) {
+        Node pos = q.front().first;
+        int cost = q.front().second;
+        q.pop();
+        // (n, n) 위치에 로봇이 도달했다면, 최단 거리이므로 반환
+        if ((pos.pos1X == n && pos.pos1Y == n) || (pos.pos2X == n && pos.pos2Y == n)) {
+            return cost;
+        }
+        // 현재 위치에서 이동할 수 있는 위치 확인
+        vector<Node> nextPos = getNextPos(pos, newBoard);
+        for (int i = 0; i < nextPos.size(); i++) {
+            // 아직 방문하지 않은 위치라면 큐에 삽입하고 방문 처리
+            bool check = true;
+            Node pos = nextPos[i];
+            for (int j = 0; j < visited.size(); j++) {
+                if (pos.pos1X == visited[j].pos1X && pos.pos1Y == visited[j].pos1Y && pos.pos2X == visited[j].pos2X && pos.pos2Y == visited[j].pos2Y) {
+                    check = false;
+                    break;
+                }
+            }
+            if (check) {
+                q.push({pos, cost + 1});
+                visited.push_back(pos);
+            }
+        }
+    }
+    return 0;
+}
diff --git a/13/8.java b/13/8.java
new file mode 100644
index 0000000..4329e56
--- /dev/null
+++ b/13/8.java
@@ -0,0 +1,127 @@
+import java.util.*;
+
+class Node {
+    private int pos1X;
+    private int pos1Y;
+    private int pos2X;
+    private int pos2Y;
+    private int distance;
+
+    public int getPos1X() {
+        return this.pos1X;
+    }
+    public int getPos1Y() {
+        return this.pos1Y;
+    }
+    public int getPos2X() {
+        return this.pos2X;
+    }
+    public int getPos2Y() {
+        return this.pos2Y;
+    }
+    public int getDistance() {
+        return this.distance;
+    }
+
+    public Node(int pos1X, int pos1Y, int pos2X, int pos2Y, int distance) {
+        this.pos1X = pos1X;
+        this.pos1Y = pos1Y;
+        this.pos2X = pos2X;
+        this.pos2Y = pos2Y;
+        this.distance = distance;
+    }
+}
+
+class Solution {
+
+    public ArrayList<Node> getNextPos(Node pos, int[][] board) {
+        // 반환 결과(이동 가능한 위치들)
+        ArrayList<Node> nextPos = new ArrayList<Node>();
+        // (상, 하, 좌, 우)로 이동하는 경우에 대해서 처리
+        int[] dx = {-1, 1, 0, 0};
+        int[] dy = {0, 0, -1, 1};
+        for (int i = 0; i < 4; i++) {
+            int pos1NextX = pos.getPos1X() + dx[i];
+            int pos1NextY = pos.getPos1Y() + dy[i];
+            int pos2NextX = pos.getPos2X() + dx[i];
+            int pos2NextY = pos.getPos2Y() + dy[i];
+            int distanceNext = pos.getDistance() + 1;
+            // 이동하고자 하는 두 칸이 모두 비어 있다면
+            if (board[pos1NextX][pos1NextY] == 0 && board[pos2NextX][pos2NextY] == 0) {
+                nextPos.add(new Node(pos1NextX, pos1NextY, pos2NextX, pos2NextY, distanceNext));
+            }
+        }
+        // 현재 로봇이 가로로 놓여 있는 경우
+        int[] hor = {-1, 1};
+        if (pos.getPos1X() == pos.getPos2X()) {
+            for (int i = 0; i < 2; i++) { // 위쪽으로 회전하거나, 아래쪽으로 회전
+                // 위쪽 혹은 아래쪽 두 칸이 모두 비어 있다면
+                if (board[pos.getPos1X() + hor[i]][pos.getPos1Y()] == 0 && board[pos.getPos2X() + hor[i]][pos.getPos2Y()] == 0) {
+                    nextPos.add(new Node(pos.getPos1X(), pos.getPos1Y(), pos.getPos1X() + hor[i], pos.getPos1Y(), pos.getDistance() + 1));
+                    nextPos.add(new Node(pos.getPos2X(), pos.getPos2Y(), pos.getPos2X() + hor[i], pos.getPos2Y(), pos.getDistance() + 1));
+                }
+            }
+        }
+        // 현재 로봇이 세로로 놓여 있는 경우
+        int[] ver = {-1, 1};
+        if (pos.getPos1Y() == pos.getPos2Y()) {
+            for (int i = 0; i < 2; i++) { // 왼쪽으로 회전하거나, 오른쪽으로 회전
+                // 왼쪽 혹은 오른쪽 두 칸이 모두 비어 있다면
+                if (board[pos.getPos1X()][pos.getPos1Y() + ver[i]] == 0 && board[pos.getPos2X()][pos.getPos2Y() + ver[i]] == 0) {
+                    nextPos.add(new Node(pos.getPos1X(), pos.getPos1Y(), pos.getPos1X(), pos.getPos1Y() + ver[i], pos.getDistance() + 1));
+                    nextPos.add(new Node(pos.getPos2X(), pos.getPos2Y(), pos.getPos2X(), pos.getPos2Y() + ver[i], pos.getDistance() + 1));
+                }
+            }
+        }
+        // 현재 위치에서 이동할 수 있는 위치를 반환
+        return nextPos;
+    }
+    
+    public int solution(int[][] board) {
+        // 맵 외곽에 벽을 두는 형태로 맵 변형
+        int n = board.length;
+        int[][] newBoard = new int[n + 2][n + 2];
+        for (int i = 0; i < n + 2; i++) {
+            for (int j = 0; j < n + 2; j++) {
+                newBoard[i][j] = 1;
+            }
+        }
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                newBoard[i + 1][j + 1] = board[i][j];
+            }
+        }
+        // 너비 우선 탐색(BFS) 수행
+        Queue<Node> q = new LinkedList<>();
+        ArrayList<Node> visited = new ArrayList<>();
+        Node pos = new Node(1, 1, 1, 2, 0); // 시작 위치 설정
+        q.offer(pos); // 큐에 삽입한 뒤에
+        visited.add(pos); // 방문 처리
+        // 큐가 빌 때까지 반복
+        while (!q.isEmpty()) {
+            pos = q.poll();
+            // (n, n) 위치에 로봇이 도달했다면, 최단 거리이므로 반환
+            if ((pos.getPos1X() == n && pos.getPos1Y() == n) || (pos.getPos2X() == n && pos.getPos2Y() == n)) {
+                return pos.getDistance();
+            }
+            // 현재 위치에서 이동할 수 있는 위치 확인
+            ArrayList<Node> nextPos = getNextPos(pos, newBoard);
+            for (int i = 0; i < nextPos.size(); i++) {
+                // 아직 방문하지 않은 위치라면 큐에 삽입하고 방문 처리
+                boolean check = true;
+                pos = nextPos.get(i);
+                for (int j = 0; j < visited.size(); j++) {
+                    if (pos.getPos1X() == visited.get(j).getPos1X() && pos.getPos1Y() == visited.get(j).getPos1Y() && pos.getPos2X() == visited.get(j).getPos2X() && pos.getPos2Y() == visited.get(j).getPos2Y()) {
+                        check = false;
+                        break;
+                    }
+                }
+                if (check) {
+                    q.offer(pos);
+                    visited.add(pos);
+                }
+            }
+        }
+        return 0;
+    }
+}
diff --git a/13/8.py b/13/8.py
index b0c91ec..ec4cdb3 100644
--- a/13/8.py
+++ b/13/8.py
@@ -2,14 +2,14 @@
 
 def get_next_pos(pos, board):
     next_pos = [] # 반환 결과 (이동 가능한 위치들)
-    pos = list(pos) # 현재 위치
+    pos = list(pos) # 현재 위치 정보를 리스트로 변환 (집합 → 리스트)
     pos1_x, pos1_y, pos2_x, pos2_y = pos[0][0], pos[0][1], pos[1][0], pos[1][1]
     # (상, 하, 좌, 우)로 이동하는 경우에 대해서 처리
     dx = [-1, 1, 0, 0]
     dy = [0, 0, -1, 1]
     for i in range(4):
         pos1_next_x, pos1_next_y, pos2_next_x, pos2_next_y = pos1_x + dx[i], pos1_y + dy[i], pos2_x + dx[i], pos2_y + dy[i]
-        # 이동하고자 하는 두 칸이 모두 비어있다면
+        # 이동하고자 하는 두 칸이 모두 비어 있다면
         if board[pos1_next_x][pos1_next_y] == 0 and board[pos2_next_x][pos2_next_y] == 0:
             next_pos.append({(pos1_next_x, pos1_next_y), (pos2_next_x, pos2_next_y)})
     # 현재 로봇이 가로로 놓여 있는 경우
diff --git a/14/1.cpp b/14/1.cpp
new file mode 100644
index 0000000..b4d7da6
--- /dev/null
+++ b/14/1.cpp
@@ -0,0 +1,58 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+class Student {
+public:
+    string name;
+    int kor;
+    int eng;
+    int m;
+    Student(string name, int kor, int eng, int m) {
+        this->name = name;
+        this->kor = kor;
+        this->eng = eng;
+        this->m = m;
+    }
+    /*
+    [ 정렬 기준 ]
+    1) 두 번째 원소를 기준으로 내림차순 정렬
+    2) 두 번째 원소가 같은 경우, 세 번째 원소를 기준으로 오름차순 정렬
+    3) 세 번째 원소가 같은 경우, 네 번째 원소를 기준으로 내림차순 정렬
+    4) 네 번째 원소가 같은 경우, 첫 번째 원소를 기준으로 오름차순 정렬
+    */
+    bool operator <(Student &other) {
+        if (this->kor == other.kor && this->eng == other.eng && this->m == other.m) {
+            return this->name < other.name;
+        }
+        if (this->kor == other.kor && this->eng == other.eng) {
+            return this->m > other.m;
+        }
+        if (this->kor == other.kor) {
+            return this->eng < other.eng;
+        }
+        return this->kor > other.kor;
+    }
+};
+
+int n;
+vector<Student> v;
+
+int main(void) {
+    cin >> n;
+    for (int i = 0; i < n; i++) {
+        string name;
+        int kor;
+        int eng;
+        int m;
+        cin >> name >> kor >> eng >> m;
+        v.push_back(Student(name, kor, eng, m));
+    }
+
+    sort(v.begin(), v.end());
+
+    // 정렬된 학생 정보에서 이름만 출력
+    for (int i = 0; i < n; i++) {
+        cout << v[i].name << '\n';
+    }
+}
\ No newline at end of file
diff --git a/14/1.java b/14/1.java
new file mode 100644
index 0000000..7c1a206
--- /dev/null
+++ b/14/1.java
@@ -0,0 +1,67 @@
+import java.util.*;
+
+class Student implements Comparable<Student> {
+
+    private String name;
+    private int kor;
+    private int eng;
+    private int m;
+
+    public Student(String name, int kor, int eng, int m) {
+        this.name = name;
+        this.kor = kor;
+        this.eng = eng;
+        this.m = m;
+    }
+
+    /*
+    [ 정렬 기준 ]
+    1) 두 번째 원소를 기준으로 내림차순 정렬
+    2) 두 번째 원소가 같은 경우, 세 번째 원소를 기준으로 오름차순 정렬
+    3) 세 번째 원소가 같은 경우, 네 번째 원소를 기준으로 내림차순 정렬
+    4) 네 번째 원소가 같은 경우, 첫 번째 원소를 기준으로 오름차순 정렬
+    */
+
+    public String getName() {
+        return this.name;
+    }
+
+    // 정렬 기준은 '점수가 낮은 순서'
+    @Override
+    public int compareTo(Student other) {
+        if (this.kor == other.kor && this.eng == other.eng && this.m == other.m) {
+            return this.name.compareTo(other.name);
+        }
+        if (this.kor == other.kor && this.eng == other.eng) {
+            return Integer.compare(other.m, this.m);
+        }
+        if (this.kor == other.kor) {
+            return Integer.compare(this.eng, other.eng);
+        }
+        return Integer.compare(other.kor, this.kor);
+    }
+}
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        int n = sc.nextInt();
+
+        ArrayList<Student> students = new ArrayList<>();
+        for (int i = 0; i < n; i++) {
+            String name = sc.next();
+            int kor = sc.nextInt();
+            int eng = sc.nextInt();
+            int m = sc.nextInt();
+            students.add(new Student(name, kor, eng, m));
+        }
+
+        Collections.sort(students);
+
+        // 정렬된 학생 정보에서 이름만 출력
+        for (int i = 0; i < n; i++) {
+            System.out.println(students.get(i).getName());
+        }
+    }
+}
\ No newline at end of file
diff --git a/14/1.py b/14/1.py
index 61852a0..b8cb1f7 100644
--- a/14/1.py
+++ b/14/1.py
@@ -1,10 +1,19 @@
 n = int(input())
-students = []
+students = [] # 학생 정보를 담을 리스트
 
+# 모든 학생 정보를 입력 받기
 for _ in range(n):
     students.append(input().split())
 
+'''
+[ 정렬 기준 ]
+1) 두 번째 원소를 기준으로 내림차순 정렬
+2) 두 번째 원소가 같은 경우, 세 번째 원소를 기준으로 오름차순 정렬
+3) 세 번째 원소가 같은 경우, 네 번째 원소를 기준으로 내림차순 정렬
+4) 네 번째 원소가 같은 경우, 첫 번째 원소를 기준으로 오름차순 정렬
+'''
 students.sort(key=lambda x: (-int(x[1]), int(x[2]), -int(x[3]), x[0]))
 
+# 정렬된 학생 정보에서 이름만 출력
 for student in students:
     print(student[0])
diff --git a/14/2.cpp b/14/2.cpp
new file mode 100644
index 0000000..767fcb3
--- /dev/null
+++ b/14/2.cpp
@@ -0,0 +1,20 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n;
+vector<int> v;
+
+int main(void) {
+    cin >> n;
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        v.push_back(x);
+    }
+
+    sort(v.begin(), v.end());
+
+    // 중간값(median)을 출력
+    cout << v[(n - 1) / 2] << '\n';
+}
\ No newline at end of file
diff --git a/14/2.java b/14/2.java
new file mode 100644
index 0000000..ceeceb6
--- /dev/null
+++ b/14/2.java
@@ -0,0 +1,19 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        int n = sc.nextInt();
+
+        ArrayList<Integer> arrayList = new ArrayList<>();
+        for (int i = 0; i < n; i++) {
+            arrayList.add(sc.nextInt());
+        }
+
+        Collections.sort(arrayList);
+
+        // 중간값(median)을 출력
+        System.out.println(arrayList.get((n - 1) / 2));
+    }
+}
diff --git a/14/2.py b/14/2.py
index 8aa3cfb..7bb91cb 100644
--- a/14/2.py
+++ b/14/2.py
@@ -2,5 +2,5 @@
 a = list(map(int, input().split()))
 a.sort()
 
-# Median(가운데) 값을 출력합니다.
+# 중간값(median)을 출력
 print(a[(n - 1) // 2])
diff --git a/14/3.cpp b/14/3.cpp
new file mode 100644
index 0000000..1072c8e
--- /dev/null
+++ b/14/3.cpp
@@ -0,0 +1,39 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+bool compare(pair<int, double> a, pair<int, double> b) {
+    if (a.second == b.second) return a.first < b.first;
+    return a.second > b.second;
+}
+
+vector<int> solution(int N, vector<int> stages) {
+    vector<pair<int, double> > v;
+    vector<int> answer;
+    int length = stages.size();
+
+    // 스테이지 번호를 1부터 N까지 증가시키며
+    for (int i = 1; i <= N; i++) {
+        // 해당 스테이지에 머물러 있는 사람의 수 계산
+        int cnt = count(stages.begin(), stages.end(), i);
+
+        // 실패율 계산
+        double fail = 0;
+        if (length >= 1) {
+            fail = (double) cnt / length;
+        }
+
+        // 리스트에 (스테이지 번호, 실패율) 원소 삽입
+        v.push_back({i, fail});
+        length -= cnt;
+    }
+
+    // 실패율을 기준으로 각 스테이지를 내림차순 정렬
+    sort(v.begin(), v.end(), compare);
+
+    // 정렬된 스테이지 번호 반환
+    for (int i = 0; i < N; i++) {
+        answer.push_back(v[i].first);
+    }
+    return answer;
+}
\ No newline at end of file
diff --git a/14/3.java b/14/3.java
new file mode 100644
index 0000000..9c51311
--- /dev/null
+++ b/14/3.java
@@ -0,0 +1,62 @@
+import java.util.*;
+
+class Node implements Comparable<Node> {
+
+    private int stage;
+    private double fail;
+
+    public Node(int stage, double fail) {
+        this.stage = stage;
+        this.fail = fail;
+    }
+
+    public int getStage() {
+        return this.stage;
+    }
+
+    @Override
+    public int compareTo(Node other) {
+        if (this.fail == other.fail) {
+            return Integer.compare(this.stage, other.stage);
+        }
+        return Double.compare(other.fail, this.fail);
+    }
+}
+
+class Solution {
+    public int[] solution(int N, int[] stages) {
+        int[] answer = new int[N];
+        ArrayList<Node> arrayList = new ArrayList<>();
+        int length = stages.length;
+
+        // 스테이지 번호를 1부터 N까지 증가시키며
+        for (int i = 1; i <= N; i++) {
+            // 해당 스테이지에 머물러 있는 사람의 수 계산
+            int cnt = 0;
+            for (int j = 0; j < stages.length; j++) {
+                if (stages[j] == i) {
+                    cnt += 1;
+                }
+            }
+
+            // 실패율 계산
+            double fail = 0;
+            if (length >= 1) {
+                fail = (double) cnt / length;
+            }
+
+            // 리스트에 (스테이지 번호, 실패율) 원소 삽입
+            arrayList.add(new Node(i, fail));
+            length -= cnt;
+        }
+
+        // 실패율을 기준으로 각 스테이지를 내림차순 정렬
+        Collections.sort(arrayList);
+
+        // 정렬된 스테이지 번호 반환
+        for (int i = 0; i < N; i++) {
+            answer[i] = arrayList.get(i).getStage();
+        }
+        return answer;
+    }
+}
\ No newline at end of file
diff --git a/14/3.py b/14/3.py
index 7e767f4..982b97b 100644
--- a/14/3.py
+++ b/14/3.py
@@ -2,6 +2,7 @@ def solution(N, stages):
     answer = []
     length = len(stages)
 
+    # 스테이지 번호를 1부터 N까지 증가시키며
     for i in range(1, N + 1):
         # 해당 스테이지에 머물러 있는 사람의 수 계산
         count = stages.count(i)
@@ -12,13 +13,13 @@ def solution(N, stages):
         else:
             fail = count / length
         
-        # 리스트에 원소 삽입
+        # 리스트에 (스테이지 번호, 실패율) 원소 삽입
         answer.append((i, fail))
         length -= count
 
     # 실패율을 기준으로 각 스테이지를 내림차순 정렬
     answer = sorted(answer, key=lambda t: t[1], reverse=True)
     
-    # 정렬된 스테이지 번호 출력
+    # 정렬된 스테이지 번호 반환
     answer = [i[0] for i in answer]
     return answer
diff --git a/14/4.cpp b/14/4.cpp
new file mode 100644
index 0000000..7130b76
--- /dev/null
+++ b/14/4.cpp
@@ -0,0 +1,32 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, result;
+priority_queue<int> pq;
+
+int main(void) {
+    cin >> n;
+
+    // 힙(Heap)에 초기 카드 묶음을 모두 삽입
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        pq.push(-x);
+    }
+
+    // 힙(Heap)에 원소가 1개 남을 때까지
+    while (pq.size() != 1) {
+        // 가장 작은 2개의 카드 묶음 꺼내기
+        int one = -pq.top();
+        pq.pop();
+        int two = -pq.top();
+        pq.pop();
+        // 카드 묶음을 합쳐서 다시 삽입
+        int summary = one + two;
+        result += summary;
+        pq.push(-summary);
+    }
+
+    cout << result << '\n';
+}
\ No newline at end of file
diff --git a/14/4.java b/14/4.java
new file mode 100644
index 0000000..c3919c0
--- /dev/null
+++ b/14/4.java
@@ -0,0 +1,30 @@
+import java.util.*;
+
+public class Main {
+
+    public static int n, result;
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        n = sc.nextInt();
+
+        PriorityQueue<Integer> pq = new PriorityQueue<>();
+        // 힙(Heap)에 초기 카드 묶음을 모두 삽입
+        for (int i = 0; i < n; i++) {
+            pq.offer(sc.nextInt());
+        }
+
+        // 힙(Heap)에 원소가 1개 남을 때까지
+        while (pq.size() != 1) {
+            // 가장 작은 2개의 카드 묶음 꺼내기
+            int one = pq.poll();
+            int two = pq.poll();
+            // 카드 묶음을 합쳐서 다시 삽입
+            int summary = one + two;
+            result += summary;
+            pq.offer(summary);
+        }
+
+        System.out.println(result);
+    }
+}
\ No newline at end of file
diff --git a/14/4.py b/14/4.py
index a445df8..f98f199 100644
--- a/14/4.py
+++ b/14/4.py
@@ -1,14 +1,23 @@
 import heapq
+
 n = int(input())
+
+# 힙(Heap)에 초기 카드 묶음을 모두 삽입
 heap = []
 for i in range(n):
     data = int(input())
     heapq.heappush(heap, data)
+
 result = 0
+
+# 힙(Heap)에 원소가 1개 남을 때까지
 while len(heap) != 1:
+    # 가장 작은 2개의 카드 묶음 꺼내기
     one = heapq.heappop(heap)
     two = heapq.heappop(heap)
+    # 카드 묶음을 합쳐서 다시 삽입
     sum_value = one + two
     result += sum_value
     heapq.heappush(heap, sum_value)
+
 print(result)
diff --git a/15/1.cpp b/15/1.cpp
new file mode 100644
index 0000000..f91119c
--- /dev/null
+++ b/15/1.cpp
@@ -0,0 +1,37 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수
+int countByRange(vector<int>& v, int leftValue, int rightValue) {
+    vector<int>::iterator rightIndex = upper_bound(v.begin(), v.end(), rightValue);
+    vector<int>::iterator leftIndex = lower_bound(v.begin(), v.end(), leftValue);
+    return rightIndex - leftIndex;
+}
+
+int n, x;
+vector<int> v;
+
+int main() {
+    // 데이터의 개수 N, 찾고자 하는 값 x 입력받기
+    cin >> n >> x;
+
+    // 전체 데이터 입력 받기
+    for (int i = 0; i < n; i++) {
+        int temp;
+        cin >> temp;
+        v.push_back(temp);
+    }
+
+    // 값이 [x, x] 범위에 있는 데이터의 개수 계산
+    int cnt = countByRange(v, x, x);
+
+    // 값이 x인 원소가 존재하지 않는다면
+    if (cnt == 0) {
+        cout << -1 << '\n';
+    }
+    //  값이 x인 원소가 존재한다면
+    else {
+        cout << cnt << '\n';
+    }
+}
diff --git a/15/1.java b/15/1.java
new file mode 100644
index 0000000..896f2a6
--- /dev/null
+++ b/15/1.java
@@ -0,0 +1,52 @@
+import java.util.*;
+
+public class Main {
+
+    public static int lowerBound(int[] arr, int target, int start, int end) {
+        while (start < end) {
+            int mid = (start + end) / 2;
+            if (arr[mid] >= target) end = mid;
+            else start = mid + 1;
+        }
+        return end;
+    }
+
+    public static int upperBound(int[] arr, int target, int start, int end) {
+        while (start < end) {
+            int mid = (start + end) / 2;
+            if (arr[mid] > target) end = mid;
+            else start = mid + 1;
+        }
+        return end;
+    }
+
+    // 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수
+    public static int countByRange(int[] arr, int leftValue, int rightValue) {
+        // 유의: lowerBound와 upperBound는 end 변수의 값을 배열의 길이로 설정
+        int rightIndex = upperBound(arr, rightValue, 0, arr.length);
+        int leftIndex = lowerBound(arr, leftValue, 0, arr.length);
+        return rightIndex - leftIndex;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        // 데이터의 개수 N, 찾고자 하는 값 x 입력받기
+        int n = sc.nextInt();
+        int x = sc.nextInt();
+
+        // 전체 데이터 입력받기
+        int[] arr = new int[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+        
+        // 값이 [x, x] 범위에 있는 데이터의 개수 계산
+        int cnt = countByRange(arr, x, x);
+        
+        // 값이 x인 원소가 존재하지 않는다면
+        if (cnt == 0) System.out.println(-1);
+        //  값이 x인 원소가 존재한다면
+        else System.out.println(cnt);
+    }
+}
diff --git a/15/1.py b/15/1.py
new file mode 100644
index 0000000..a1993ca
--- /dev/null
+++ b/15/1.py
@@ -0,0 +1,20 @@
+from bisect import bisect_left, bisect_right
+
+# 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수
+def count_by_range(array, left_value, right_value):
+    right_index = bisect_right(array, right_value)
+    left_index = bisect_left(array, left_value)
+    return right_index - left_index
+
+n, x = map(int, input().split()) # 데이터의 개수 N, 찾고자 하는 값 x 입력 받기
+array = list(map(int, input().split())) # 전체 데이터 입력 받기
+
+# 값이 [x, x] 범위에 있는 데이터의 개수 계산
+count = count_by_range(array, x, x)
+
+# 값이 x인 원소가 존재하지 않는다면
+if count == 0:
+    print(-1)
+# 값이 x인 원소가 존재한다면
+else:
+    print(count)
diff --git a/15/2.cpp b/15/2.cpp
new file mode 100644
index 0000000..7a85f52
--- /dev/null
+++ b/15/2.cpp
@@ -0,0 +1,33 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 이진 탐색 소스코드 구현(재귀 함수)
+int binarySearch(vector<int>& arr, int start, int end) {
+    if (start > end) return -1;
+    int mid = (start + end) / 2;
+    // 고정점을 찾은 경우 중간점 인덱스 반환
+    if (arr[mid] == mid) return mid;
+    // 중간점의 값보다 중간점이 작은 경우 왼쪽 확인
+    else if (arr[mid] > mid) return binarySearch(arr, start, mid - 1);
+    // 중간점의 값보다 중간점이 큰 경우 오른쪽 확인
+    else return binarySearch(arr, mid + 1, end);
+}
+
+int n;
+vector<int> arr;
+
+int main(void) {
+    cin >> n;
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+
+    // 이진 탐색(Binary Search) 수행
+    int index = binarySearch(arr, 0, n - 1);
+
+    // 결과 출력
+    cout << index << '\n';
+}
\ No newline at end of file
diff --git a/15/2.java b/15/2.java
new file mode 100644
index 0000000..f0058e9
--- /dev/null
+++ b/15/2.java
@@ -0,0 +1,32 @@
+import java.util.*;
+
+public class Main {
+
+    // 이진 탐색 소스코드 구현(재귀 함수)
+    public static int binarySearch(int[] arr, int start, int end) {
+        if (start > end) return -1;
+        int mid = (start + end) / 2;
+        // 고정점을 찾은 경우 중간점 인덱스 반환
+        if (arr[mid] == mid) return mid;
+        // 중간점의 값보다 중간점이 작은 경우 왼쪽 확인
+        else if (arr[mid] > mid) return binarySearch(arr, start, mid - 1);
+        // 중간점의 값보다 중간점이 큰 경우 오른쪽 확인
+        else return binarySearch(arr, mid + 1, end);
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        int n = sc.nextInt();
+        int[] arr = new int[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+        
+        // 이진 탐색(Binary Search) 수행
+        int index = binarySearch(arr, 0, n - 1);
+
+        // 결과 출력
+        System.out.println(index);
+    }
+}
diff --git a/15/2.py b/15/2.py
new file mode 100644
index 0000000..86e85ef
--- /dev/null
+++ b/15/2.py
@@ -0,0 +1,27 @@
+# 이진 탐색 소스코드 구현(재귀 함수)
+def binary_search(array, start, end):
+    if start > end:
+        return None
+    mid = (start + end) // 2
+    # 고정점을 찾은 경우 인덱스 반환
+    if array[mid] == mid:
+        return mid
+    # 중간점이 가리키는 값보다 중간점이 작은 경우 왼쪽 확인
+    elif array[mid] > mid:
+        return binary_search(array, start, mid - 1)
+    # 중간점이 가리키는 값보다 중간점이 큰 경우 오른쪽 확인
+    else:
+        return binary_search(array, mid + 1, end)
+
+n = int(input())
+array = list(map(int, input().split()))
+
+# 이진 탐색(Binary Search) 수행
+index = binary_search(array, 0, n - 1)
+
+# 고정점이 없는 경우 -1 출력
+if index == None:
+    print(-1)
+# 고정점이 있는 경우 해당 인덱스 출력
+else:
+    print(index)
diff --git a/15/3.cpp b/15/3.cpp
new file mode 100644
index 0000000..b889665
--- /dev/null
+++ b/15/3.cpp
@@ -0,0 +1,50 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 집의 개수(N)와 공유기의 개수(C)
+int n, c;
+vector<int> arr;
+
+int main() {
+    cin >> n >> c;
+
+    // 전체 집의 좌표 정보를 입력 받기
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+    // 이진 탐색 수행을 위해 정렬 수행
+    sort(arr.begin(), arr.end());
+
+    int start = 1; // 가능한 최소 거리(min gap)
+    int end = arr[n - 1] - arr[0]; // 가능한 최대 거리(max gap)
+    int result = 0;
+
+    while (start <= end) {
+        // mid는 가장 인접한 두 공유기 사이의 거리(gap)을 의미
+        int mid = (start + end) / 2;
+        // 첫째 집에는 무조건 공유기를 설치한다고 가정
+        int value = arr[0];
+        int cnt = 1;
+        // 현재의 mid 값을 이용해 공유기를 설치하기
+        for (int i = 1; i < n; i++) { // 앞에서부터 차근차근 설치
+            if (arr[i] >= value + mid) {
+                value = arr[i];
+                cnt += 1;
+            }
+        }
+        // C개 이상의 공유기를 설치할 수 있는 경우, 거리를 증가시키기
+        if (cnt >= c) {
+            start = mid + 1;
+            result = mid; // 최적의 결과를 저장
+        }
+        // C개 이상의 공유기를 설치할 수 없는 경우, 거리를 감소시키기
+        else {
+            end = mid - 1;
+        }
+    }
+
+    cout << result << '\n';
+}
diff --git a/15/3.java b/15/3.java
new file mode 100644
index 0000000..7e55cb6
--- /dev/null
+++ b/15/3.java
@@ -0,0 +1,49 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        //  집의 개수(N)와 공유기의 개수(C)를 입력받기
+        Scanner sc = new Scanner(System.in);
+        int n = sc.nextInt();
+        int c = sc.nextInt();
+
+        // 전체 집의 좌표 정보를 입력받기
+        ArrayList<Integer> arr = new ArrayList<>();
+        for (int i = 0; i < n; i++) {
+            arr.add(sc.nextInt());
+        }
+
+        // 이진 탐색을 위해 정렬 수행
+        Collections.sort(arr);
+
+        int start = 1; // 가능한 최소 거리(min gap)
+        int end = arr.get(n - 1) - arr.get(0); // 가능한 최대 거리(max gap)
+        int result = 0;
+
+        while (start <= end) {
+            // mid는 가장 인접한 두 공유기 사이의 거리(gap)을 의미
+            int mid = (start + end) / 2;
+            // 첫째 집에는 무조건 공유기를 설치한다고 가정
+            int value = arr.get(0);
+            int cnt = 1;
+            // 현재의 mid 값을 이용해 공유기를 설치하기
+            for (int i = 1; i < n; i++) { // 앞에서부터 차근차근 설치
+                if (arr.get(i) >= value + mid) {
+                    value = arr.get(i);
+                    cnt += 1;
+                }
+            }
+            // C개 이상의 공유기를 설치할 수 있는 경우, 거리를 증가시키기
+            if (cnt >= c) {
+                start = mid + 1;
+                result = mid; // 최적의 결과를 저장
+            }
+            // C개 이상의 공유기를 설치할 수 없는 경우, 거리를 감소시키기
+            else {
+                end = mid - 1;
+            }
+        }
+        System.out.println(result);
+    }
+}
diff --git a/15/3.py b/15/3.py
new file mode 100644
index 0000000..574c194
--- /dev/null
+++ b/15/3.py
@@ -0,0 +1,30 @@
+# 집의 개수(N)와 공유기의 개수(C)를 입력 받기
+n, c = list(map(int, input().split(' ')))
+
+# 전체 집의 좌표 정보를 입력 받기
+array = []
+for _ in range(n):
+     array.append(int(input()))
+array.sort() # 이진 탐색 수행을 위해 정렬 수행
+
+start = 1 # 가능한 최소 거리(min gap)
+end = array[-1] - array[0] # 가능한 최대 거리(max gap)
+result = 0
+
+while(start <= end):
+    mid = (start + end) // 2 # mid는 가장 인접한 두 공유기 사이의 거리(gap)을 의미
+    # 첫째 집에는 무조건 공유기를 설치한다고 가정
+    value = array[0]
+    count = 1
+    # 현재의 mid 값을 이용해 공유기를 설치하기
+    for i in range(1, n): # 앞에서부터 차근차근 설치 
+        if array[i] >= value + mid:
+            value = array[i]
+            count += 1
+    if count >= c: # C개 이상의 공유기를 설치할 수 있는 경우, 거리를 증가시키기
+        start = mid + 1
+        result = mid # 최적의 결과를 저장
+    else: # C개 이상의 공유기를 설치할 수 없는 경우, 거리를 감소시키기
+        end = mid - 1
+
+print(result)
diff --git a/15/4.cpp b/15/4.cpp
new file mode 100644
index 0000000..1a20140
--- /dev/null
+++ b/15/4.cpp
@@ -0,0 +1,61 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수
+int countByRange(vector<string>& v, string leftValue, string rightValue) {
+    vector<string>::iterator rightIndex = upper_bound(v.begin(), v.end(), rightValue);
+    vector<string>::iterator leftIndex = lower_bound(v.begin(), v.end(), leftValue);
+    return rightIndex - leftIndex;
+}
+
+// 문자열 내에서 특정한 문자열을 다른 문자열로 모두 치환하는 함수
+string replaceAll(string str, string from, string to){
+    string res = str;
+    int pos = 0;
+    while((pos = res.find(from, pos)) != string::npos) 
+    {
+        res.replace(pos, from.size(), to);
+        pos += to.size();
+    }
+    return res;
+}
+
+// 모든 단어들을 길이마다 나누어서 저장하기 위한 리스트
+vector<string> arr[10001];
+// 모든 단어들을 길이마다 나누어서 뒤집어 저장하기 위한 리스트
+vector<string> reversed_arr[10001];
+
+vector<int> solution(vector<string> words, vector<string> queries) {
+    vector<int> answer;
+    
+    // 모든 단어를 접미사 와일드카드 배열, 접두사 와일드카드 배열에 각각 삽입
+    for (int i = 0; i < words.size(); i++) {
+        string word = words[i];
+        arr[word.size()].push_back(word); // 단어를 삽입
+        reverse(word.begin(), word.end());
+        reversed_arr[word.size()].push_back(word); // 단어를 뒤집어서 삽입
+    }
+    
+    // 이진 탐색을 수행하기 위해 각 단어 리스트 정렬 수행
+    for (int i = 0; i < 10001; i++) {
+        sort(arr[i].begin(), arr[i].end());
+        sort(reversed_arr[i].begin(), reversed_arr[i].end());
+    }
+    
+    // 쿼리를 하나씩 확인하며 처리
+    for (int i = 0; i < queries.size(); i++) {
+        string q = queries[i];
+        int res = 0;
+        if (q[0] != '?') { // 접미사에 와일드 카드가 붙은 경우
+            res = countByRange(arr[q.size()], replaceAll(q, "?", "a"), replaceAll(q, "?", "z"));
+        }
+        else { // 접두사에 와일드 카드가 붙은 경우
+            reverse(q.begin(), q.end());
+            res = countByRange(reversed_arr[q.size()], replaceAll(q, "?", "a"), replaceAll(q, "?", "z")); 
+        }
+        // 검색된 단어의 개수를 저장
+        answer.push_back(res);
+    }
+    return answer;
+}
\ No newline at end of file
diff --git a/15/4.java b/15/4.java
new file mode 100644
index 0000000..09e91c7
--- /dev/null
+++ b/15/4.java
@@ -0,0 +1,83 @@
+import java.util.*;
+
+class Solution {
+
+    public int lowerBound(ArrayList<String> arr, String target, int start, int end) {
+        while (start < end) {
+            int mid = (start + end) / 2;
+            // arr[mid]가 target보다 사전순으로 같거나 뒤에 있다면
+            if (arr.get(mid).compareTo(target) >= 0) end = mid;
+            else start = mid + 1;
+        }
+        return end;
+    }
+
+    public int upperBound(ArrayList<String> arr, String target, int start, int end) {
+        while (start < end) {
+            int mid = (start + end) / 2;
+            // arr[mid]가 target보다 사전순으로 뒤에 있다면
+            if (arr.get(mid).compareTo(target) > 0) end = mid;
+            else start = mid + 1;
+        }
+        return end;
+    }
+
+    // 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수
+    public int countByRange(ArrayList<String> arr, String leftValue, String rightValue) {
+        // 유의: lowerBound와 upperBound는 end 변수의 값을 배열의 길이로 설정
+        int rightIndex = upperBound(arr, rightValue, 0, arr.size());
+        int leftIndex = lowerBound(arr, leftValue, 0, arr.size());
+        return rightIndex - leftIndex;
+    }
+
+    // 모든 단어들을 길이마다 나누어서 저장하기 위한 리스트
+    public ArrayList<ArrayList<String>> arr = new ArrayList<ArrayList<String>>();
+    // 모든 단어들을 길이마다 나누어서 뒤집어 저장하기 위한 리스트
+    public ArrayList<ArrayList<String>> reversedArr = new ArrayList<ArrayList<String>>();
+
+    public int[] solution(String[] words, String[] queries) {
+        ArrayList<Integer> ans = new ArrayList<Integer>();
+
+        // 단어의 길이는 10,000까지 가능
+        for (int i = 0; i < 10001; i++) {
+            arr.add(new ArrayList<String>());
+            reversedArr.add(new ArrayList<String>());
+        }
+
+        // 모든 단어를 접미사 와일드카드 배열, 접두사 와일드카드 배열에 각각 삽입
+        for (int i = 0; i < words.length; i++) {
+            String word = words[i];
+            arr.get(word.length()).add(word); // 단어를 삽입
+            word = (new StringBuffer(word)).reverse().toString();
+            reversedArr.get(word.length()).add(word); // 단어를 뒤집어서 삽입
+        }
+
+        // 이진 탐색을 수행하기 위해 각 단어 리스트 정렬 수행
+        for (int i = 0; i < 10001; i++) {
+            Collections.sort(arr.get(i));
+            Collections.sort(reversedArr.get(i));
+        }
+
+        // 쿼리를 하나씩 확인하며 처리
+        for (int i = 0; i < queries.length; i++) {
+            String q = queries[i];
+            int res = 0;
+            if (q.charAt(0) != '?') { // 접미사에 와일드 카드가 붙은 경우
+                res = countByRange(arr.get(q.length()), q.replaceAll("\\?", "a"), q.replaceAll("\\?", "z"));
+            }
+            else { // 접두사에 와일드 카드가 붙은 경우
+                q = (new StringBuffer(q)).reverse().toString();
+                res = countByRange(reversedArr.get(q.length()), q.replaceAll("\\?", "a"), q.replaceAll("\\?", "z")); 
+            }
+            // 검색된 단어의 개수를 저장
+            ans.add(res);
+        }
+
+        // 배열로 바꾸어 반환
+        int[] answer = new int[ans.size()];
+        for (int i = 0; i < ans.size(); i++) {
+            answer[i] = ans.get(i);
+        }
+        return answer;
+    }
+}
diff --git a/15/4.py b/15/4.py
new file mode 100644
index 0000000..e3ba65f
--- /dev/null
+++ b/15/4.py
@@ -0,0 +1,31 @@
+from bisect import bisect_left, bisect_right
+
+# 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수
+def count_by_range(a, left_value, right_value):
+    right_index = bisect_right(a, right_value)
+    left_index = bisect_left(a, left_value)
+    return right_index - left_index
+
+# 모든 단어들을 길이마다 나누어서 저장하기 위한 리스트
+array = [[] for _ in range(10001)]
+# 모든 단어들을 길이마다 나누어서 뒤집어 저장하기 위한 리스트
+reversed_array = [[] for _ in range(10001)]
+
+def solution(words, queries):
+    answer = []
+    for word in words: # 모든 단어를 접미사 와일드카드 배열, 접두사 와일드카드 배열에 각각 삽입
+        array[len(word)].append(word) # 단어를 삽입
+        reversed_array[len(word)].append(word[::-1]) # 단어를 뒤집어서 삽입
+
+    for i in range(10001): # 이진 탐색을 수행하기 위해 각 단어 리스트 정렬 수행
+        array[i].sort()
+        reversed_array[i].sort()
+
+    for q in queries: # 쿼리를 하나씩 확인하며 처리
+        if q[0] != '?': # 접미사에 와일드 카드가 붙은 경우
+            res = count_by_range(array[len(q)], q.replace('?', 'a'), q.replace('?', 'z'))
+        else: # 접두사에 와일드 카드가 붙은 경우
+            res = count_by_range(reversed_array[len(q)], q[::-1].replace('?', 'a'), q[::-1].replace('?', 'z'))
+        # 검색된 단어의 개수를 저장
+        answer.append(res)
+    return answer
diff --git a/16/1.cpp b/16/1.cpp
new file mode 100644
index 0000000..ea1ac83
--- /dev/null
+++ b/16/1.cpp
@@ -0,0 +1,47 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int testCase, n, m;
+int arr[20][20];
+int dp[20][20];
+
+int main(void) {
+    // 테스트 케이스(Test Case) 입력
+    cin >> testCase;
+    for (int tc = 0; tc < testCase; tc++) {
+        // 금광 정보 입력
+        cin >> n >> m;
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                cin >> arr[i][j];
+            }
+        }
+        // 다이나믹 프로그래밍을 위한 2차원 DP 테이블 초기화
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                dp[i][j] = arr[i][j];
+            }
+        }
+        // 다이나믹 프로그래밍 진행
+        for (int j = 1; j < m; j++) {
+            for (int i = 0; i < n; i++) {
+                int leftUp, leftDown, left;
+                // 왼쪽 위에서 오는 경우
+                if (i == 0) leftUp = 0;
+                else leftUp = dp[i - 1][j - 1];
+                // 왼쪽 아래에서 오는 경우
+                if (i == n - 1) leftDown = 0;
+                else leftDown = dp[i + 1][j - 1];
+                // 왼쪽에서 오는 경우
+                left = dp[i][j - 1];
+                dp[i][j] = dp[i][j] + max(leftUp, max(leftDown, left));
+            }
+        }
+        int result = 0;
+        for (int i = 0; i < n; i++) {
+            result = max(result, dp[i][m - 1]);
+        }
+        cout << result << '\n';
+    }
+}
diff --git a/16/1.java b/16/1.java
new file mode 100644
index 0000000..e82761d
--- /dev/null
+++ b/16/1.java
@@ -0,0 +1,50 @@
+import java.util.*;
+
+public class Main {
+	
+    static int testCase, n, m;
+    static int[][] arr = new int[20][20];
+    static int[][] dp = new int[20][20];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        // 테스트 케이스(Test Case) 입력
+        testCase = sc.nextInt();
+        for (int tc = 0; tc < testCase; tc++) {
+            // 금광 정보 입력
+            n = sc.nextInt();
+            m = sc.nextInt();
+            for (int i = 0; i < n; i++) {
+                for (int j = 0; j < m; j++) {
+                    arr[i][j] = sc.nextInt();
+                }
+            }
+            // 다이나믹 프로그래밍을 위한 2차원 DP 테이블 초기화
+            for (int i = 0; i < n; i++) {
+                for (int j = 0; j < m; j++) {
+                    dp[i][j] = arr[i][j];
+                }
+            }
+            // 다이나믹 프로그래밍 진행
+            for (int j = 1; j < m; j++) {
+                for (int i = 0; i < n; i++) {
+                    int leftUp, leftDown, left;
+                    // 왼쪽 위에서 오는 경우
+                    if (i == 0) leftUp = 0;
+                    else leftUp = dp[i - 1][j - 1];
+                    // 왼쪽 아래에서 오는 경우
+                    if (i == n - 1) leftDown = 0;
+                    else leftDown = dp[i + 1][j - 1];
+                    // 왼쪽에서 오는 경우
+                    left = dp[i][j - 1];
+                    dp[i][j] = dp[i][j] + Math.max(leftUp, Math.max(leftDown, left));
+                }
+            }
+            int result = 0;
+            for (int i = 0; i < n; i++) {
+                result = Math.max(result, dp[i][m - 1]);
+            }
+            System.out.println(result);
+        }
+    }
+}
\ No newline at end of file
diff --git a/16/1.py b/16/1.py
index 6444641..4b86c30 100644
--- a/16/1.py
+++ b/16/1.py
@@ -2,13 +2,13 @@
 for tc in range(int(input())):
     # 금광 정보 입력
     n, m = map(int, input().split())
-    data = list(map(int, input().split()))
+    array = list(map(int, input().split()))
 
     # 다이나믹 프로그래밍을 위한 2차원 DP 테이블 초기화
     dp = []
     index = 0
     for i in range(n):
-        dp.append(data[index:index + m])
+        dp.append(array[index:index + m])
         index += m
 
     # 다이나믹 프로그래밍 진행
diff --git a/16/2.cpp b/16/2.cpp
new file mode 100644
index 0000000..7839a4d
--- /dev/null
+++ b/16/2.cpp
@@ -0,0 +1,34 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n;
+int dp[500][500]; // 다이나믹 프로그래밍을 위한 DP 테이블 초기화
+
+int main(void) {
+    cin >> n;
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < i + 1; j++) {
+            cin >> dp[i][j];
+        }
+    }
+    // 다이나믹 프로그래밍으로 2번째 줄부터 내려가면서 확인
+    for (int i = 1; i < n; i++) {
+        for (int j = 0; j <= i; j++) {
+            int upLeft, up;
+            // 왼쪽 위에서 내려오는 경우
+            if (j == 0) upLeft = 0;
+            else upLeft = dp[i - 1][j - 1];
+            // 바로 위에서 내려오는 경우
+            if (j == i) up = 0;
+            else up = dp[i - 1][j];
+            // 최대 합을 저장
+            dp[i][j] = dp[i][j] + max(upLeft, up);
+        }
+    }
+    int result = 0;
+    for (int i = 0; i < n; i++) {
+        result = max(result, dp[n - 1][i]);
+    }
+    cout << result << '\n';
+}
\ No newline at end of file
diff --git a/16/2.java b/16/2.java
new file mode 100644
index 0000000..a480f1f
--- /dev/null
+++ b/16/2.java
@@ -0,0 +1,36 @@
+import java.util.*;
+
+public class Main {
+	
+    static int n;
+    static int[][] dp = new int[500][500]; // 다이나믹 프로그래밍을 위한 DP 테이블 초기화
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        n = sc.nextInt();
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < i + 1; j++) {
+                dp[i][j] = sc.nextInt();
+            }
+        }
+        // 다이나믹 프로그래밍으로 2번째 줄부터 내려가면서 확인
+        for (int i = 1; i < n; i++) {
+            for (int j = 0; j <= i; j++) {
+                int upLeft, up;
+                // 왼쪽 위에서 내려오는 경우
+                if (j == 0) upLeft = 0;
+                else upLeft = dp[i - 1][j - 1];
+                // 바로 위에서 내려오는 경우
+                if (j == i) up = 0;
+                else up = dp[i - 1][j];
+                // 최대 합을 저장
+                dp[i][j] = dp[i][j] + Math.max(upLeft, up);
+            }
+        }
+        int result = 0;
+        for (int i = 0; i < n; i++) {
+            result = Math.max(result, dp[n - 1][i]);
+        }
+        System.out.println(result);
+    }
+}
\ No newline at end of file
diff --git a/16/2.py b/16/2.py
index 4ed65b3..3af6fa5 100644
--- a/16/2.py
+++ b/16/2.py
@@ -1,8 +1,8 @@
 n = int(input())
-data = []
+dp = [] # 다이나믹 프로그래밍을 위한 DP 테이블 초기화
 
 for _ in range(n):
-    data.append(list(map(int, input().split())))
+    dp.append(list(map(int, input().split())))
 
 # 다이나믹 프로그래밍으로 2번째 줄부터 내려가면서 확인
 for i in range(1, n):
@@ -11,13 +11,13 @@
         if j == 0:
             up_left = 0
         else:
-            up_left = data[i - 1][j - 1]
+            up_left = dp[i - 1][j - 1]
         # 바로 위에서 내려오는 경우
         if j == i:
             up = 0
         else:
-            up = data[i - 1][j]
+            up = dp[i - 1][j]
         # 최대 합을 저장
-        data[i][j] = data[i][j] + max(up_left, up)
+        dp[i][j] = dp[i][j] + max(up_left, up)
 
-print(max(data[n - 1]))
+print(max(dp[n - 1]))
diff --git a/16/3.cpp b/16/3.cpp
new file mode 100644
index 0000000..7b29a39
--- /dev/null
+++ b/16/3.cpp
@@ -0,0 +1,35 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n; // 전체 상담 개수
+vector<int> t; // 각 상담을 완료하는데 걸리는 기간
+vector<int> p; // 각 상담을 완료했을 때 받을 수 있는 금액
+int dp[16]; // 다이나믹 프로그래밍을 위한 1차원 DP 테이블 초기화
+int maxValue;
+
+int main(void) {
+    cin >> n;
+
+    for (int i = 0; i < n; i++) {
+        int x, y;
+        cin >> x >> y;
+        t.push_back(x);
+        p.push_back(y);
+    }
+
+    // 리스트를 뒤에서부터 거꾸로 확인
+    for (int i = n - 1; i >= 0; i--) {
+        int time = t[i] + i;
+        // 상담이 기간 안에 끝나는 경우
+        if (time <= n) {
+            // 점화식에 맞게, 현재까지의 최고 이익 계산
+            dp[i] = max(p[i] + dp[time], maxValue);
+            maxValue = dp[i];
+        }
+        // 상담이 기간을 벗어나는 경우
+        else dp[i] = maxValue;
+    }
+
+    cout << maxValue << '\n';
+}
diff --git a/16/3.java b/16/3.java
new file mode 100644
index 0000000..e848ab7
--- /dev/null
+++ b/16/3.java
@@ -0,0 +1,35 @@
+import java.util.*;
+
+public class Main {
+	
+    static int n; // 전체 상담 개수
+    static int[] t = new int[15]; // 각 상담을 완료하는데 걸리는 기간
+    static int[] p = new int[15]; // 각 상담을 완료했을 때 받을 수 있는 금액
+    static int[] dp = new int[16]; // 다이나믹 프로그래밍을 위한 1차원 DP 테이블 초기화
+    static int maxValue;
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        n = sc.nextInt();
+
+        for (int i = 0; i < n; i++) {
+            t[i] = sc.nextInt();
+            p[i] = sc.nextInt();
+        }
+
+        // 배열을 뒤에서부터 거꾸로 확인
+        for (int i = n - 1; i >= 0; i--) {
+            int time = t[i] + i;
+            // 상담이 기간 안에 끝나는 경우
+            if (time <= n) {
+                // 점화식에 맞게, 현재까지의 최고 이익 계산
+                dp[i] = Math.max(p[i] + dp[time], maxValue);
+                maxValue = dp[i];
+            }
+            // 상담이 기간을 벗어나는 경우
+            else dp[i] = maxValue;
+        }
+
+        System.out.println(maxValue);
+    }
+}
\ No newline at end of file
diff --git a/16/3.py b/16/3.py
index 040101d..704aab8 100644
--- a/16/3.py
+++ b/16/3.py
@@ -1,7 +1,7 @@
-n = int(input())
-t = []
-p = []
-dp = [0] * (n + 1)
+n = int(input()) # 전체 상담 개수
+t = [] # 각 상담을 완료하는데 걸리는 기간
+p = [] # 각 상담을 완료했을 때 받을 수 있는 금액
+dp = [0] * (n + 1) # 다이나믹 프로그래밍을 위한 1차원 DP 테이블 초기화
 max_value = 0
 
 for _ in range(n):
@@ -21,4 +21,4 @@
     else:
         dp[i] = max_value
 
-print(max(dp))
+print(max_value)
diff --git a/16/4.cpp b/16/4.cpp
new file mode 100644
index 0000000..6138d71
--- /dev/null
+++ b/16/4.cpp
@@ -0,0 +1,41 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n;
+vector<int> v;
+
+int main(void) {
+    cin >> n;
+
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        v.push_back(x);
+    }
+
+    // 순서를 뒤집어 '최장 증가 부분 수열' 문제로 변환
+    reverse(v.begin(), v.end());
+
+    // 다이나믹 프로그래밍을 위한 1차원 DP 테이블 초기화
+    int dp[2000]; 
+    for (int i = 0; i < n; i++) {
+        dp[i] = 1;
+    }
+
+    // 가장 긴 증가하는 부분 수열(LIS) 알고리즘 수행
+    for (int i = 1; i < n; i++) {
+        for (int j = 0; j < i; j++) {
+            if (v[j] < v[i]) {
+                dp[i] = max(dp[i], dp[j] + 1);
+            }
+        }
+    }
+    
+    // 열외해야 하는 병사의 최소 수를 출력
+    int maxValue = 0;
+    for (int i = 0; i < n; i++) {
+        maxValue = max(maxValue, dp[i]);
+    }
+    cout << n - maxValue << '\n';
+}
\ No newline at end of file
diff --git a/16/4.java b/16/4.java
new file mode 100644
index 0000000..27f5c9f
--- /dev/null
+++ b/16/4.java
@@ -0,0 +1,41 @@
+import java.util.*;
+
+public class Main {
+	
+    static int n;
+    static ArrayList<Integer> v = new ArrayList<Integer>();
+    static int[] dp = new int[2000];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        n = sc.nextInt();
+
+        for (int i = 0; i < n; i++) {
+            v.add(sc.nextInt());
+        }
+
+        // 순서를 뒤집어 '최장 증가 부분 수열' 문제로 변환
+        Collections.reverse(v);
+
+        // 다이나믹 프로그래밍을 위한 1차원 DP 테이블 초기화
+        for (int i = 0; i < n; i++) {
+            dp[i] = 1;
+        }
+
+        // 가장 긴 증가하는 부분 수열(LIS) 알고리즘 수행
+        for (int i = 1; i < n; i++) {
+            for (int j = 0; j < i; j++) {
+                if (v.get(j) < v.get(i)) {
+                    dp[i] = Math.max(dp[i], dp[j] + 1);
+                }
+            }
+        }
+
+        // 열외해야 하는 병사의 최소 수를 출력
+        int maxValue = 0;
+        for (int i = 0; i < n; i++) {
+            maxValue = Math.max(maxValue, dp[i]);
+        }
+        System.out.println(n - maxValue);
+    }
+}
\ No newline at end of file
diff --git a/16/4.py b/16/4.py
index 60a3b80..bee94df 100644
--- a/16/4.py
+++ b/16/4.py
@@ -1,13 +1,15 @@
 n = int(input())
-data = list(map(int, input().split()))
-# 순서를 바꾸어 '최장 증가 부분 수열' 문제로 변환
-data.reverse()
+array = list(map(int, input().split()))
+# 순서를 뒤집어 '최장 증가 부분 수열' 문제로 변환
+array.reverse()
 
-# LCS 알고리즘 수행
+# 다이나믹 프로그래밍을 위한 1차원 DP 테이블 초기화
 dp = [1] * n
+
+# 가장 긴 증가하는 부분 수열(LIS) 알고리즘 수행
 for i in range(1, n):
     for j in range(0, i):
-        if data[j] < data[i]:
+        if array[j] < array[i]:
             dp[i] = max(dp[i], dp[j] + 1)
 
 # 열외해야 하는 병사의 최소 수를 출력
diff --git a/16/5.cpp b/16/5.cpp
new file mode 100644
index 0000000..c4f5c3f
--- /dev/null
+++ b/16/5.cpp
@@ -0,0 +1,38 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n;
+int ugly[1000]; // 못생긴 수를 담기 위한 테이블 (1차원 DP 테이블)
+
+int main(void) {
+    cin >> n;
+
+    // 2배, 3배, 5배를 위한 인덱스
+    int i2 = 0, i3 = 0, i5 = 0;
+    // 처음에 곱셈 값을 초기화
+    int next2 = 2, next3 = 3, next5 = 5;
+
+    ugly[0] = 1; // 첫 번째 못생긴 수는 1
+    // 1부터 n까지의 못생긴 수들을 찾기
+    for (int l = 1; l < n; l++) {
+        // 가능한 곱셈 결과 중에서 가장 작은 수를 선택
+        ugly[l] = min(next2, min(next3, next5));
+        // 인덱스에 따라서 곱셈 결과를 증가
+        if (ugly[l] == next2) {
+            i2 += 1;
+            next2 = ugly[i2] * 2;
+        }
+        if (ugly[l] == next3) {
+            i3 += 1;
+            next3 = ugly[i3] * 3;
+        }
+        if (ugly[l] == next5) {
+            i5 += 1;
+            next5 = ugly[i5] * 5;
+        }
+    }
+
+    // n번째 못생긴 수를 출력
+    cout << ugly[n - 1] << '\n';
+}
\ No newline at end of file
diff --git a/16/5.java b/16/5.java
new file mode 100644
index 0000000..f5212b8
--- /dev/null
+++ b/16/5.java
@@ -0,0 +1,40 @@
+import java.util.*;
+
+public class Main {
+	
+    static int n;
+    static int[] ugly = new int[1000]; // 못생긴 수를 담기 위한 테이블 (1차원 DP 테이블)
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        n = sc.nextInt();
+
+        // 2배, 3배, 5배를 위한 인덱스
+        int i2 = 0, i3 = 0, i5 = 0;
+        // 처음에 곱셈 값을 초기화
+        int next2 = 2, next3 = 3, next5 = 5;
+
+        ugly[0] = 1; // 첫 번째 못생긴 수는 1
+        // 1부터 n까지의 못생긴 수들을 찾기
+        for (int l = 1; l < n; l++) {
+            // 가능한 곱셈 결과 중에서 가장 작은 수를 선택
+            ugly[l] = Math.min(next2, Math.min(next3, next5));
+            // 인덱스에 따라서 곱셈 결과를 증가
+            if (ugly[l] == next2) {
+                i2 += 1;
+                next2 = ugly[i2] * 2;
+            }
+            if (ugly[l] == next3) {
+                i3 += 1;
+                next3 = ugly[i3] * 3;
+            }
+            if (ugly[l] == next5) {
+                i5 += 1;
+                next5 = ugly[i5] * 5;
+            }
+        }
+
+        // n번째 못생긴 수를 출력
+        System.out.println(ugly[n - 1]);
+    }
+}
\ No newline at end of file
diff --git a/16/5.py b/16/5.py
index 5763f56..b546154 100644
--- a/16/5.py
+++ b/16/5.py
@@ -1,30 +1,27 @@
-# n번째 못생긴 수를 찾는 함수
-def solve(n):
-    ugly = [0] * n # 못생긴 수를 담기 위한 테이블
-    ugly[0] = 1 # 첫 번째 못생긴 수는 1
+n = int(input())
 
-    # 2배, 3배, 5배를 위한 인덱스
-    i2 = i3 = i5 = 0
-    # 처음에 곱셈 값을 초기화
-    next2, next3, next5 = 2, 3, 5
+ugly = [0] * n # 못생긴 수를 담기 위한 테이블 (1차원 DP 테이블)
+ugly[0] = 1 # 첫 번째 못생긴 수는 1
 
-    # 1부터 n까지의 못생긴 수들을 찾기
-    for l in range(1, n):
-        # 가능한 곱셈 결과 중에서 가장 작은 수를 선택
-        ugly[l] = min(next2, next3, next5)
-        # 인덱스에 따라서 곱셈 결과를 증가
-        if ugly[l] == next2:
-            i2 += 1
-            next2 = ugly[i2] * 2
-        if ugly[l] == next3:
-            i3 += 1
-            next3 = ugly[i3] * 3
-        if ugly[l] == next5:
-            i5 += 1
-            next5 = ugly[i5] * 5
+# 2배, 3배, 5배를 위한 인덱스
+i2 = i3 = i5 = 0
+# 처음에 곱셈 값을 초기화
+next2, next3, next5 = 2, 3, 5
 
-    # n번째 못생긴 수를 출력
-    return ugly[n - 1]
+# 1부터 n까지의 못생긴 수들을 찾기
+for l in range(1, n):
+    # 가능한 곱셈 결과 중에서 가장 작은 수를 선택
+    ugly[l] = min(next2, next3, next5)
+    # 인덱스에 따라서 곱셈 결과를 증가
+    if ugly[l] == next2:
+        i2 += 1
+        next2 = ugly[i2] * 2
+    if ugly[l] == next3:
+        i3 += 1
+        next3 = ugly[i3] * 3
+    if ugly[l] == next5:
+        i5 += 1
+        next5 = ugly[i5] * 5
 
-n = int(input())
-print(solve(n))
+# n번째 못생긴 수를 출력
+print(ugly[n - 1])
diff --git a/16/5_notice.md b/16/5_notice.md
new file mode 100644
index 0000000..5b5e3bb
--- /dev/null
+++ b/16/5_notice.md
@@ -0,0 +1,15 @@
+예를 들어 먼저 못생긴 수로 1이 있다고 해보자. 이때 각각 2의 배수, 3의 배수, 5의 배수를 구하면 다음과 같다.
+
+* 2의 배수: 1 X 2 = 2
+* 3의 배수: 1 X 3 = 3
+* 5의 배수: 1 X 5 = 5
+
+이로써 우리는 새롭게 2, 3, 5 또한 못생긴 수에 해당한다는 것을 알 수 있다. 따라서 이를 고려했을때, 전체 못생긴 수는 {1, 2, 3, 5}가 된다.
+
+첫 번째로 못생긴 수인 1에 이어서 그다음으로 못생긴 수는 2가 된다. 이때 각각 2의 배수, 3의 배수, 5의 배수를 구하면 다음과 같다.
+
+* 2의 배수: 2 X 2 = 4
+* 3의 배수: 2 X 3 = 6
+* 5의 배수: 2 X 5 = 10
+
+이로써 우리는 4, 6, 10이 못생긴 수에 해당한다는 것을 알 수 있다. 따라서 이를 고려했을 때, 전체 못생긴 수는 {1, 2, 3, 4, 5, 6, 10}이 된다. 이렇게 못생긴 수들을 작은 수부터 차례대로 확인하면서, 각 못생긴 수에 대해서 2의 배수, 3의 배수, 5의 배수를 고려한다는 점을 기억하여 효율적으로 소스코드를 작성하면 다음과 같이 작성할 수 있다.
diff --git a/16/6.cpp b/16/6.cpp
new file mode 100644
index 0000000..fbb24aa
--- /dev/null
+++ b/16/6.cpp
@@ -0,0 +1,47 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 두 문자열을 입력 받기
+string str1;
+string str2; 
+
+// 최소 편집 거리(Edit Distance) 계산을 위한 다이나믹 프로그래밍
+int editDist(string str1, string str2) {
+    int n = str1.size();
+    int m = str2.size();
+
+    // 다이나믹 프로그래밍을 위한 2차원 DP 테이블 초기화
+    vector<vector<int> > dp(n + 1, vector<int>(m + 1));
+
+    // DP 테이블 초기 설정
+    for (int i = 1; i <= n; i++) {
+        dp[i][0] = i;
+    }
+    for (int j = 1; j <= m; j++) {
+        dp[0][j] = j;
+    }
+
+    // 최소 편집 거리 계산
+    for (int i = 1; i <= n; i++) {
+        for (int j = 1; j <= m; j++) {
+            // 문자가 같다면, 왼쪽 위에 해당하는 수를 그대로 대입
+            if (str1[i - 1] == str2[j - 1]) {
+                dp[i][j] = dp[i - 1][j - 1];
+            }
+            // 문자가 다르다면, 세 가지 경우 중에서 최솟값 찾기
+            else { // 삽입(왼쪽), 삭제(위쪽), 교체(왼쪽 위) 중에서 최소 비용을 찾아 대입
+                dp[i][j] = 1 + min(dp[i][j - 1], min(dp[i - 1][j], dp[i - 1][j - 1]));
+            }
+        }
+    }
+
+    return dp[n][m];
+}
+
+int main(void) {
+    cin >> str1 >> str2;
+
+    // 최소 편집 거리 출력
+    cout << editDist(str1, str2) << '\n';
+}
\ No newline at end of file
diff --git a/16/6.java b/16/6.java
new file mode 100644
index 0000000..4e44b24
--- /dev/null
+++ b/16/6.java
@@ -0,0 +1,50 @@
+import java.util.*;
+
+public class Main {
+	
+    static String str1;
+    static String str2;
+
+    // 최소 편집 거리(Edit Distance) 계산을 위한 다이나믹 프로그래밍
+    static int editDist(String str1, String str2) {
+        int n = str1.length();
+        int m = str2.length();
+
+        // 다이나믹 프로그래밍을 위한 2차원 DP 테이블 초기화
+        int[][] dp = new int[n + 1][m + 1];
+
+        // DP 테이블 초기 설정
+        for (int i = 1; i <= n; i++) {
+            dp[i][0] = i;
+        }
+        for (int j = 1; j <= m; j++) {
+            dp[0][j] = j;
+        }
+
+        // 최소 편집 거리 계산
+        for (int i = 1; i <= n; i++) {
+            for (int j = 1; j <= m; j++) {
+                // 문자가 같다면, 왼쪽 위에 해당하는 수를 그대로 대입
+                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
+                    dp[i][j] = dp[i - 1][j - 1];
+                }
+                // 문자가 다르다면, 세 가지 경우 중에서 최솟값 찾기
+                else { // 삽입(왼쪽), 삭제(위쪽), 교체(왼쪽 위) 중에서 최소 비용을 찾아 대입
+                    dp[i][j] = 1 + Math.min(dp[i][j - 1], Math.min(dp[i - 1][j], dp[i - 1][j - 1]));
+                }
+            }
+        }
+
+        return dp[n][m];
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        String str1 = sc.next();
+        String str2 = sc.next();
+
+        // 최소 편집 거리 출력
+        System.out.println(editDist(str1, str2));
+    }
+}
\ No newline at end of file
diff --git a/16/6.py b/16/6.py
index ee7eff8..6ccf896 100644
--- a/16/6.py
+++ b/16/6.py
@@ -1,29 +1,32 @@
-str1 = input()
-str2 = input()
-
-# 최소 편집 거리 계산을 위한 다이나믹 프로그래밍
+# 최소 편집 거리(Edit Distance) 계산을 위한 다이나믹 프로그래밍
 def edit_dist(str1, str2):
     n = len(str1)
     m = len(str2)
 
-    # 이차원 테이블을 초기화
+    # 다이나믹 프로그래밍을 위한 2차원 DP 테이블 초기화
     dp = [[0] * (m + 1) for _ in range(n + 1)]
 
-    for i in range(n + 1):
-        for j in range(m + 1):
-            # 문자열 A가 비어 있다면, 문자열 B로 모든 문자를 삽입
-            if i == 0:
-                dp[i][j] = j
-            # 문자열 B가 비어 있다면, 문자열 A로 모든 문자를 삽입
-            elif j == 0:
-                dp[i][j] = i
-            # 문자가 같다면, 왼쪽 위에 해당하는 수를 그대로 가져옴
-            elif str1[i-1] == str2[j-1]:
-                dp[i][j] = dp[i-1][j-1]
-            # 마지막 문자가 다르다면, 모든 경우의 수 중에서 최솟값 찾기
-            else: # 삽입, 삭제, 교체 중에서 최소 비용을 찾아 삽입
-                dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1])
+    # DP 테이블 초기 설정
+    for i in range(1, n + 1):
+        dp[i][0] = i
+    for j in range(1, m + 1):
+        dp[0][j] = j
+    
+    # 최소 편집 거리 계산
+    for i in range(1, n + 1):
+        for j in range(1, m + 1):
+            # 문자가 같다면, 왼쪽 위에 해당하는 수를 그대로 대입
+            if str1[i - 1] == str2[j - 1]:
+                dp[i][j] = dp[i - 1][j - 1]
+            # 문자가 다르다면, 세 가지 경우 중에서 최솟값 찾기
+            else: # 삽입(왼쪽), 삭제(위쪽), 교체(왼쪽 위) 중에서 최소 비용을 찾아 대입
+                dp[i][j] = 1 + min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1])
 
     return dp[n][m]
 
+# 두 문자열을 입력 받기
+str1 = input()
+str2 = input()
+
+# 최소 편집 거리 출력
 print(edit_dist(str1, str2))
diff --git a/17/1.cpp b/17/1.cpp
new file mode 100644
index 0000000..321ff69
--- /dev/null
+++ b/17/1.cpp
@@ -0,0 +1,58 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+// 노드의 개수(N), 간선의 개수(M)
+int n, m;
+// 2차원 배열(그래프 표현)를 만들기
+int graph[101][101];
+
+int main(void) {
+    cin >> n >> m;
+
+    // 최단 거리 테이블을 모두 무한으로 초기화
+    for (int i = 0; i < 101; i++) {
+        fill(graph[i], graph[i] + 101, INF);
+    }
+
+    // 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+    for (int a = 1; a <= n; a++) {
+        for (int b = 1; b <= n; b++) {
+            if (a == b) graph[a][b] = 0;
+        }
+    }
+
+    // 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
+    for (int i = 0; i < m; i++) {
+        // A에서 B로 가는 비용은 C라고 설정
+        int a, b, c;
+        cin >> a >> b >> c;
+        // 가장 짧은 간선 정보만 저장
+        if (c < graph[a][b]) graph[a][b] = c;
+    }
+    
+    // 점화식에 따라 플로이드 워셜 알고리즘을 수행
+    for (int k = 1; k <= n; k++) {
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b]);
+            }
+        }
+    }
+
+    // 수행된 결과를 출력
+    for (int a = 1; a <= n; a++) {
+        for (int b = 1; b <= n; b++) {
+            // 도달할 수 없는 경우, 0을 출력
+            if (graph[a][b] == INF) {
+                cout << 0 << ' ';
+            }
+            // 도달할 수 있는 경우 거리를 출력
+            else {
+                cout << graph[a][b] << ' ';
+            }
+        }
+        cout << '\n';
+    }
+}
\ No newline at end of file
diff --git a/17/1.java b/17/1.java
new file mode 100644
index 0000000..087e507
--- /dev/null
+++ b/17/1.java
@@ -0,0 +1,63 @@
+import java.util.*;
+
+public class Main {
+
+    public static final int INF = (int) 1e9; // 무한을 의미하는 값으로 10억을 설정
+    // 노드의 개수(N), 간선의 개수(M)
+    public static int n, m;
+    // 2차원 배열(그래프 표현)를 만들기
+    public static int[][] graph = new int[101][101];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        // 최단 거리 테이블을 모두 무한으로 초기화
+        for (int i = 0; i < 101; i++) {
+            Arrays.fill(graph[i], INF);
+        }
+
+        // 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                if (a == b) graph[a][b] = 0;
+            }
+        }
+
+        // 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
+        for (int i = 0; i < m; i++) {
+            // A에서 B로 가는 비용은 C라고 설정
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            int c = sc.nextInt();
+            // 가장 짧은 간선 정보만 저장
+            if (c < graph[a][b]) graph[a][b] = c;
+        }
+
+        // 점화식에 따라 플로이드 워셜 알고리즘을 수행
+        for (int k = 1; k <= n; k++) {
+            for (int a = 1; a <= n; a++) {
+                for (int b = 1; b <= n; b++) {
+                    graph[a][b] = Math.min(graph[a][b], graph[a][k] + graph[k][b]);
+                }
+            }
+        }
+
+        // 수행된 결과를 출력
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                // 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
+                if (graph[a][b] == INF) {
+                    System.out.print(0 + " ");
+                }
+                // 도달할 수 있는 경우 거리를 출력
+                else {
+                    System.out.print(graph[a][b] + " ");
+                }
+            }
+            System.out.println();
+        }
+    }
+}
\ No newline at end of file
diff --git a/17/1.py b/17/1.py
new file mode 100644
index 0000000..1dfda4a
--- /dev/null
+++ b/17/1.py
@@ -0,0 +1,38 @@
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
+
+# 노드의 개수 및 간선의 개수를 입력받기
+n = int(input())
+m = int(input())
+# 2차원 리스트(그래프 표현)를 만들고, 모든 값을 무한으로 초기화
+graph = [[INF] * (n + 1) for _ in range(n + 1)]
+
+# 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+for a in range(1, n + 1):
+    for b in range(1, n + 1):
+        if a == b:
+            graph[a][b] = 0
+
+# 각 간선에 대한 정보를 입력받아, 그 값으로 초기화
+for _ in range(m):
+    # A에서 B로 가는 비용은 C라고 설정
+    a, b, c = map(int, input().split())
+    # 가장 짧은 간선 정보만 저장
+    if c < graph[a][b]:
+        graph[a][b] = c
+
+# 점화식에 따라 플로이드 워셜 알고리즘을 수행
+for k in range(1, n + 1):
+    for a in range(1, n + 1):
+        for b in range(1, n + 1):
+            graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])
+
+# 수행된 결과를 출력
+for a in range(1, n + 1):
+    for b in range(1, n + 1):
+        # 도달할 수 없는 경우, 0을 출력
+        if graph[a][b] == INF:
+            print(0, end=" ")
+        # 도달할 수 있는 경우 거리를 출력
+        else:
+            print(graph[a][b], end=" ")
+    print()
diff --git a/17/2.cpp b/17/2.cpp
new file mode 100644
index 0000000..af2950c
--- /dev/null
+++ b/17/2.cpp
@@ -0,0 +1,57 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+// 노드의 개수(N), 간선의 개수(M)
+int n, m;
+// 2차원 배열(그래프 표현)를 만들기
+int graph[501][501];
+
+int main(void) {
+    cin >> n >> m;
+
+    // 최단 거리 테이블을 모두 무한으로 초기화
+    for (int i = 0; i < 501; i++) {
+        fill(graph[i], graph[i] + 501, INF);
+    }
+
+    // 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+    for (int a = 1; a <= n; a++) {
+        for (int b = 1; b <= n; b++) {
+            if (a == b) graph[a][b] = 0;
+        }
+    }
+
+    // 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
+    for (int i = 0; i < m; i++) {
+        // A에서 B로 가는 비용은 C라고 설정
+        int a, b;
+        cin >> a >> b;
+        graph[a][b] = 1;
+    }
+    
+    // 점화식에 따라 플로이드 워셜 알고리즘을 수행
+    for (int k = 1; k <= n; k++) {
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b]);
+            }
+        }
+    }
+
+    int result = 0;
+    // 각 학생을 번호에 따라 한 명씩 확인하며 도달 가능한지 체크
+    for (int i = 1; i <= n; i++) {
+        int cnt = 0;
+        for (int j = 1; j <= n; j++) {
+            if (graph[i][j] != INF || graph[j][i] != INF) {
+                cnt += 1;
+            }
+        }
+        if (cnt == n) {
+            result += 1;
+        }
+    }
+    cout << result << '\n';
+}
\ No newline at end of file
diff --git a/17/2.java b/17/2.java
new file mode 100644
index 0000000..c24b382
--- /dev/null
+++ b/17/2.java
@@ -0,0 +1,61 @@
+import java.util.*;
+
+public class Main {
+
+    public static final int INF = (int) 1e9; // 무한을 의미하는 값으로 10억을 설정
+    // 노드의 개수(N), 간선의 개수(M)
+    public static int n, m;
+    // 2차원 배열(그래프 표현)를 만들기
+    public static int[][] graph = new int[501][501];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        // 최단 거리 테이블을 모두 무한으로 초기화
+        for (int i = 0; i < 501; i++) {
+            Arrays.fill(graph[i], INF);
+        }
+
+        // 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                if (a == b) graph[a][b] = 0;
+            }
+        }
+
+        // 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
+        for (int i = 0; i < m; i++) {
+            // A에서 B로 가는 비용은 C라고 설정
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            graph[a][b] = 1;
+        }
+
+        // 점화식에 따라 플로이드 워셜 알고리즘을 수행
+        for (int k = 1; k <= n; k++) {
+            for (int a = 1; a <= n; a++) {
+                for (int b = 1; b <= n; b++) {
+                    graph[a][b] = Math.min(graph[a][b], graph[a][k] + graph[k][b]);
+                }
+            }
+        }
+
+        int result = 0;
+        // 각 학생을 번호에 따라 한 명씩 확인하며 도달 가능한지 체크
+        for (int i = 1; i <= n; i++) {
+            int cnt = 0;
+            for (int j = 1; j <= n; j++) {
+                if (graph[i][j] != INF || graph[j][i] != INF) {
+                    cnt += 1;
+                }
+            }
+            if (cnt == n) {
+                result += 1;
+            }
+        }
+        System.out.println(result);
+    }
+}
\ No newline at end of file
diff --git a/17/2.py b/17/2.py
new file mode 100644
index 0000000..f8b15ef
--- /dev/null
+++ b/17/2.py
@@ -0,0 +1,35 @@
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
+
+# 노드의 개수, 간선의 개수를 입력받기
+n, m = map(int, input().split())
+# 2차원 리스트(그래프 표현)를 만들고, 모든 값을 무한으로 초기화
+graph = [[INF] * (n + 1) for _ in range(n + 1)]
+ 
+# 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+for a in range(1, n + 1):
+    for b in range(1, n + 1):
+        if a == b:
+            graph[a][b] = 0
+ 
+# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
+for _ in range(m):
+    # A에서 B로 가는 비용을 1로 설정
+    a, b = map(int, input().split())
+    graph[a][b] = 1
+ 
+# 점화식에 따라 플로이드 워셜 알고리즘을 수행
+for k in range(1, n + 1):
+    for a in range(1, n + 1):
+        for b in range(1, n + 1):
+            graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])
+
+result = 0
+# 각 학생을 번호에 따라 한 명씩 확인하며 도달 가능한지 체크
+for i in range(1, n + 1):
+    count = 0
+    for j in range(1, n + 1):
+        if graph[i][j] != INF or graph[j][i] != INF:
+            count += 1
+    if count == n:
+        result += 1
+print(result)
diff --git a/17/3.cpp b/17/3.cpp
new file mode 100644
index 0000000..6d46a87
--- /dev/null
+++ b/17/3.cpp
@@ -0,0 +1,62 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+int testCase, n;
+int graph[125][125], d[125][125];
+int dx[] = {-1, 0, 1, 0};
+int dy[] = {0, 1, 0, -1};
+
+int main(void) {
+    cin >> testCase;
+
+    // 전체 테스트 케이스(Test Case)만큼 반복
+    for (int tc = 0; tc < testCase; tc++) {
+        // 노드의 개수를 입력받기
+        cin >> n;
+
+        // 전체 맵 정보를 입력받기
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                cin >> graph[i][j];
+            }
+        }
+
+        // 최단 거리 테이블을 모두 무한으로 초기화
+        for (int i = 0; i < n; i++) {
+            fill(d[i], d[i] + 125, INF);
+        }
+
+        int x = 0, y = 0; // 시작 위치는 (0, 0)
+        // 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+        priority_queue<pair<int, pair<int, int> > > pq;
+        pq.push({-graph[x][y], {0, 0}});
+        d[x][y] = graph[x][y];
+
+        // 다익스트라 알고리즘을 수행
+        while (!pq.empty()) {
+            // 가장 최단 거리가 짧은 노드에 대한 정보 꺼내기
+            int dist = -pq.top().first;
+            int x = pq.top().second.first;
+            int y = pq.top().second.second;
+            pq.pop();
+            // 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+            if (d[x][y] < dist) continue;
+            // 현재 노드와 연결된 다른 인접한 노드들을 확인
+            for (int i = 0; i < 4; i++) {
+                int nx = x + dx[i];
+                int ny = y + dy[i];
+                // 맵의 범위를 벗어나는 경우 무시
+                if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
+                int cost = dist + graph[nx][ny];
+                // 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+                if (cost < d[nx][ny]) {
+                    d[nx][ny] = cost;
+                    pq.push({-cost, {nx, ny}});
+                }
+            }
+        }
+        cout << d[n - 1][n - 1] << '\n';
+    }
+}
\ No newline at end of file
diff --git a/17/3.java b/17/3.java
new file mode 100644
index 0000000..bf9cb39
--- /dev/null
+++ b/17/3.java
@@ -0,0 +1,98 @@
+import java.util.*;
+
+class Node implements Comparable<Node> {
+
+    private int x;
+    private int y;
+    private int distance;
+
+    public Node(int x, int y, int distance) {
+        this.x = x;
+        this.y = y;
+        this.distance = distance;
+    }
+
+    public int getX() {
+        return this.x;
+    }
+
+    public int getY() {
+        return this.y;
+    }
+
+    public int getDistance() {
+        return this.distance;
+    }
+
+    // 거리(비용)가 짧은 것이 높은 우선순위를 가지도록 설정
+    @Override
+    public int compareTo(Node other) {
+        if (this.distance < other.distance) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+
+    public static final int INF = (int) 1e9; // 무한을 의미하는 값으로 10억을 설정
+    public static int[][] graph = new int [125][125];
+    public static int[][] d = new int[125][125];
+    public static int testCase, n;
+    public static int[] dx = {-1, 0, 1, 0};
+    public static int[] dy = {0, 1, 0, -1};
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        testCase = sc.nextInt();
+
+        // 전체 테스트 케이스(Test Case)만큼 반복
+        for (int tc = 0; tc < testCase; tc++) {
+            // 노드의 개수를 입력받기
+            n = sc.nextInt();
+
+            // 전체 맵 정보를 입력받기
+            for (int i = 0; i < n; i++) {
+                for (int j = 0; j < n; j++) {
+                    graph[i][j] = sc.nextInt();
+                }
+            }
+
+            // 최단 거리 테이블을 모두 무한으로 초기화
+            for (int i = 0; i < n; i++) {
+                Arrays.fill(d[i], INF);
+            }
+
+            int x = 0, y = 0; // 시작 위치는 (0, 0)
+            // 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+            PriorityQueue<Node> pq = new PriorityQueue<>();
+            pq.offer(new Node(0, 0, graph[x][y]));
+            d[x][y] = graph[x][y];
+
+            while(!pq.isEmpty()) { // 다익스트라 알고리즘을 수행
+                // 가장 최단 거리가 짧은 노드에 대한 정보 꺼내기
+                Node node = pq.poll();
+                int dist = node.getDistance();
+                x = node.getX();
+                y = node.getY();
+                // 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+                if (d[x][y] < dist) continue;
+                // 현재 노드와 연결된 다른 인접한 노드들을 확인
+                for (int i = 0; i < 4; i++) {
+                    int nx = x + dx[i];
+                    int ny = y + dy[i];
+                    // 맵의 범위를 벗어나는 경우 무시
+                    if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
+                    int cost = dist + graph[nx][ny];
+                    // 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+                    if (cost < d[nx][ny]) {
+                        d[nx][ny] = cost;
+                        pq.offer(new Node(nx, ny, cost));
+                    }
+                }
+            }
+            System.out.println(d[n - 1][n - 1]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/17/3.py b/17/3.py
new file mode 100644
index 0000000..57a2f7d
--- /dev/null
+++ b/17/3.py
@@ -0,0 +1,47 @@
+import heapq
+import sys
+input = sys.stdin.readline
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
+
+dx = [-1, 0, 1, 0]
+dy = [0, 1, 0, -1]
+
+# 전체 테스트 케이스(Test Case)만큼 반복
+for tc in range(int(input())):
+    # 노드의 개수를 입력받기
+    n = int(input())
+
+    # 전체 맵 정보를 입력받기
+    graph = []
+    for i in range(n):
+        graph.append(list(map(int, input().split())))
+
+    # 최단 거리 테이블을 모두 무한으로 초기화
+    distance = [[INF] * n for _ in range(n)]
+
+    x, y = 0, 0 # 시작 위치는 (0, 0)
+    # 시작 노드로 가기 위한 비용은 (0, 0) 위치의 값으로 설정하여, 큐에 삽입
+    q = [(graph[x][y], x, y)]
+    distance[x][y] = graph[x][y]
+
+    # 다익스트라 알고리즘을 수행
+    while q:
+          # 가장 최단 거리가 짧은 노드에 대한 정보를 꺼내기
+          dist, x, y = heapq.heappop(q)
+          # 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+          if distance[x][y] < dist:
+              continue
+          # 현재 노드와 연결된 다른 인접한 노드들을 확인
+          for i in range(4):
+              nx = x + dx[i]
+              ny = y + dy[i]
+              # 맵의 범위를 벗어나는 경우 무시
+              if nx < 0 or nx >= n or ny < 0 or ny >= n:
+                  continue
+              cost = dist + graph[nx][ny]
+              # 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+              if cost < distance[nx][ny]:
+                  distance[nx][ny] = cost
+                  heapq.heappush(q, (cost, nx, ny))
+
+    print(distance[n - 1][n - 1])
diff --git a/17/4.cpp b/17/4.cpp
new file mode 100644
index 0000000..b77c40a
--- /dev/null
+++ b/17/4.cpp
@@ -0,0 +1,77 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+// 노드의 개수(N), 간선의 개수(M)
+int n, m;
+// 시작 노드를 1번 헛간으로 설정
+int start = 1;
+// 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
+vector<pair<int, int> > graph[20001];
+// 최단 거리 테이블 만들기
+int d[20001];
+
+void dijkstra(int start) {
+    priority_queue<pair<int, int> > pq;
+    // 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+    pq.push({0, start});
+    d[start] = 0;
+    while (!pq.empty()) { // 큐가 비어있지 않다면
+        // 가장 최단 거리가 짧은 노드에 대한 정보를 꺼내기
+        int dist = -pq.top().first; // 현재 노드까지의 비용 
+        int now = pq.top().second; // 현재 노드
+        pq.pop();
+        // 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+        if (d[now] < dist) continue;
+        // 현재 노드와 연결된 다른 인접한 노드들을 확인
+        for (int i = 0; i < graph[now].size(); i++) {
+            int cost = dist + graph[now][i].second;
+            // 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+            if (cost < d[graph[now][i].first]) {
+                d[graph[now][i].first] = cost;
+                pq.push({-cost, graph[now][i].first});
+            }
+        }
+    }
+}
+
+int main(void) {
+    cin >> n >> m;
+
+    // 모든 간선 정보를 입력받기
+    for (int i = 0; i < m; i++) {
+        int a, b;
+        cin >> a >> b;
+        // a번 노드와 b번 노드의 이동 비용이 1이라는 의미(양방향)
+        graph[a].push_back({b, 1});
+        graph[b].push_back({a, 1});
+    }
+
+    // 최단 거리 테이블을 모두 무한으로 초기화
+    fill(d, d + 20001, INF);
+
+    // 다익스트라 알고리즘을 수행
+    dijkstra(start);
+
+    // 가장 최단 거리가 먼 노드 번호(동빈이가 숨을 헛간의 번호)
+    int maxNode = 0;
+    // 도달할 수 있는 노드 중에서, 가장 최단 거리가 먼 노드와의 최단 거리
+    int maxDistance = 0;
+    // 가장 최단 거리가 먼 노드와의 최단 거리와 동일한 최단 거리를 가지는 노드들의 리스트
+    vector<int> result;
+
+    for (int i = 1; i <= n; i++) {
+        if (maxDistance < d[i]) {
+            maxNode = i;
+            maxDistance = d[i];
+            result.clear();
+            result.push_back(maxNode);
+        }
+        else if (maxDistance == d[i]) {
+            result.push_back(i);
+        }
+    }
+
+    cout << maxNode << ' ' << maxDistance << ' ' << result.size() << '\n';
+}
\ No newline at end of file
diff --git a/17/4.java b/17/4.java
new file mode 100644
index 0000000..361d72d
--- /dev/null
+++ b/17/4.java
@@ -0,0 +1,114 @@
+import java.util.*;
+
+class Node implements Comparable<Node> {
+
+    private int index;
+    private int distance;
+
+    public Node(int index, int distance) {
+        this.index = index;
+        this.distance = distance;
+    }
+
+    public int getIndex() {
+        return this.index;
+    }
+
+    public int getDistance() {
+        return this.distance;
+    }
+
+    // 거리(비용)가 짧은 것이 높은 우선순위를 가지도록 설정
+    @Override
+    public int compareTo(Node other) {
+        if (this.distance < other.distance) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+
+    public static final int INF = (int) 1e9; // 무한을 의미하는 값으로 10억을 설정
+    // 노드의 개수(N), 간선의 개수(M)
+    public static int n, m;
+    // 시작 노드를 1번 헛간으로 설정
+    public static int start = 1;
+    // 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
+    public static ArrayList<ArrayList<Node>> graph = new ArrayList<ArrayList<Node>>();
+    // 최단 거리 테이블 만들기
+    public static int[] d = new int[20001];
+
+    public static void dijkstra(int start) {
+        PriorityQueue<Node> pq = new PriorityQueue<>();
+        // 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+        pq.offer(new Node(start, 0));
+        d[start] = 0;
+        while(!pq.isEmpty()) { // 큐가 비어있지 않다면
+            // 가장 최단 거리가 짧은 노드에 대한 정보 꺼내기
+            Node node = pq.poll();
+            int dist = node.getDistance(); // 현재 노드까지의 비용 
+            int now = node.getIndex(); // 현재 노드
+            // 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+            if (d[now] < dist) continue;
+            // 현재 노드와 연결된 다른 인접한 노드들을 확인
+            for (int i = 0; i < graph.get(now).size(); i++) {
+                int cost = d[now] + graph.get(now).get(i).getDistance();
+                // 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+                if (cost < d[graph.get(now).get(i).getIndex()]) {
+                    d[graph.get(now).get(i).getIndex()] = cost;
+                    pq.offer(new Node(graph.get(now).get(i).getIndex(), cost));
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        // 그래프 초기화
+        for (int i = 0; i <= n; i++) {
+            graph.add(new ArrayList<Node>());
+        }
+
+        // 모든 간선 정보를 입력받기
+        for (int i = 0; i < m; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            // a번 노드와 b번 노드의 이동 비용이 1이라는 의미(양방향)
+            graph.get(a).add(new Node(b, 1));
+            graph.get(b).add(new Node(a, 1));
+        }
+
+        // 최단 거리 테이블을 모두 무한으로 초기화
+        Arrays.fill(d, INF);
+
+        // 다익스트라 알고리즘을 수행
+        dijkstra(start);
+
+        // 가장 최단 거리가 먼 노드 번호(동빈이가 숨을 헛간의 번호)
+        int maxNode = 0;
+        // 도달할 수 있는 노드 중에서, 가장 최단 거리가 먼 노드와의 최단 거리
+        int maxDistance = 0;
+        // 가장 최단 거리가 먼 노드와의 최단 거리와 동일한 최단 거리를 가지는 노드들의 리스트
+        ArrayList<Integer> result = new ArrayList<Integer>();
+
+        for (int i = 1; i <= n; i++) {
+            if (maxDistance < d[i]) {
+                maxNode = i;
+                maxDistance = d[i];
+                result.clear();
+                result.add(maxNode);
+            }
+            else if (maxDistance == d[i]) {
+                result.add(i);
+            }
+        }
+
+        System.out.println(maxNode + " " + maxDistance + " " + result.size());
+    }
+}
\ No newline at end of file
diff --git a/17/4.py b/17/4.py
new file mode 100644
index 0000000..0572423
--- /dev/null
+++ b/17/4.py
@@ -0,0 +1,59 @@
+import heapq
+import sys
+input = sys.stdin.readline
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
+
+# 노드의 개수, 간선의 개수를 입력받기
+n, m = map(int, input().split())
+# 시작 노드를 1번 헛간으로 설정
+start = 1
+# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
+graph = [[] for i in range(n + 1)]
+# 최단 거리 테이블을 모두 무한으로 초기화
+distance = [INF] * (n + 1)
+
+# 모든 간선 정보를 입력받기
+for _ in range(m):
+    a, b = map(int, input().split())
+    # a번 노드와 b번 노드의 이동 비용이 1이라는 의미(양방향)
+    graph[a].append((b, 1))
+    graph[b].append((a, 1))
+
+def dijkstra(start):
+    q = []
+    # 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+    heapq.heappush(q, (0, start))
+    distance[start] = 0
+    while q: # 큐가 비어있지 않다면
+        # 가장 최단 거리가 짧은 노드에 대한 정보를 꺼내기
+        dist, now = heapq.heappop(q)
+        # 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+        if distance[now] < dist:
+            continue
+        # 현재 노드와 연결된 다른 인접한 노드들을 확인
+        for i in graph[now]:
+            cost = dist + i[1]
+            # 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+            if cost < distance[i[0]]:
+                distance[i[0]] = cost
+                heapq.heappush(q, (cost, i[0]))
+
+# 다익스트라 알고리즘을 수행
+dijkstra(start)
+
+# 가장 최단 거리가 먼 노드 번호(동빈이가 숨을 헛간의 번호)
+max_node = 0
+# 도달할 수 있는 노드 중에서, 가장 최단 거리가 먼 노드와의 최단 거리
+max_distance = 0
+# 가장 최단 거리가 먼 노드와의 최단 거리와 동일한 최단 거리를 가지는 노드들의 리스트
+result = []
+
+for i in range(1, n + 1):
+    if max_distance < distance[i]:
+        max_node = i
+        max_distance = distance[i]
+        result = [max_node]
+    elif max_distance == distance[i]:
+        result.append(i)
+
+print(max_node, max_distance, len(result))
diff --git a/18/1.cpp b/18/1.cpp
new file mode 100644
index 0000000..98327a9
--- /dev/null
+++ b/18/1.cpp
@@ -0,0 +1,62 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 여행지의 개수와 여행 계획에 속한 여행지의 개수
+int n, m;
+int parent[501]; // 부모 테이블 초기화
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return parent[x] = findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> n >> m;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= n; i++) {
+        parent[i] = i;
+    }
+
+    // Union 연산을 각각 수행
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < n; j++) {
+            int x;
+            cin >> x;
+            if (x == 1) { // 연결된 경우 합집합(Union) 연산 수행
+                unionParent(i + 1, j + 1);
+            }
+        }
+    }
+
+    // 여행 계획 입력받기
+    vector<int> plan;
+    for (int i = 0; i < m; i++) {
+        int x;
+        cin >> x;
+        plan.push_back(x);
+    }
+
+    bool result = true;
+    // 여행 계획에 속하는 모든 노드의 루트가 동일한지 확인
+    for (int i = 0; i < m - 1; i++) {
+        if (findParent(plan[i]) != findParent(plan[i + 1])) {
+            result = false;
+        }
+    }
+
+    // 여행 계획에 속하는 모든 노드가 서로 연결되어 있는지(루트가 동일한지) 확인
+    if (result) cout << "YES" << '\n';
+    else cout << "NO" << '\n';
+}
\ No newline at end of file
diff --git a/18/1.java b/18/1.java
new file mode 100644
index 0000000..b7f7a58
--- /dev/null
+++ b/18/1.java
@@ -0,0 +1,64 @@
+import java.util.*;
+
+public class Main {
+
+    // 여행지의 개수와 여행 계획에 속한 여행지의 개수
+    public static int n, m;
+    public static int[] parent = new int[501]; // 부모 테이블 초기화
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return parent[x] = findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= n; i++) {
+            parent[i] = i;
+        }
+
+        // Union 연산을 각각 수행
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+                int x = sc.nextInt();
+                if (x == 1) { // 연결된 경우 합집합(Union) 연산 수행
+                    unionParent(i + 1, j + 1);
+                }
+            }
+        }
+
+        // 여행 계획 입력받기
+        ArrayList<Integer> plan = new ArrayList<>();
+        for (int i = 0; i < m; i++) {
+            int x = sc.nextInt();
+            plan.add(x);
+        }
+
+        boolean result = true;
+        // 여행 계획에 속하는 모든 노드의 루트가 동일한지 확인
+        for (int i = 0; i < m - 1; i++) {
+            if (findParent(plan.get(i)) != findParent(plan.get(i + 1))) {
+                result = false;
+            }
+        }
+
+        // 여행 계획에 속하는 모든 노드가 서로 연결되어 있는지(루트가 동일한지) 확인
+        if (result) System.out.println("YES");
+        else System.out.println("NO");
+    }
+}
\ No newline at end of file
diff --git a/18/1.py b/18/1.py
new file mode 100644
index 0000000..7be435c
--- /dev/null
+++ b/18/1.py
@@ -0,0 +1,45 @@
+# 특정 원소가 속한 집합을 찾기
+def find_parent(parent, x):
+    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if parent[x] != x:
+        parent[x] = find_parent(parent, parent[x])
+    return parent[x]
+
+# 두 원소가 속한 집합을 합치기
+def union_parent(parent, a, b):
+    a = find_parent(parent, a)
+    b = find_parent(parent, b)
+    if a < b:
+        parent[b] = a
+    else:
+        parent[a] = b
+
+# 여행지의 개수와 여행 계획에 속한 여행지의 개수 입력받기
+n, m = map(int, input().split())
+parent = [0] * (n + 1) # 부모 테이블 초기화
+
+# 부모 테이블상에서, 부모를 자기 자신으로 초기화
+for i in range(1, n + 1):
+    parent[i] = i
+
+# Union 연산을 각각 수행
+for i in range(n):
+    data = list(map(int, input().split()))
+    for j in range(n):
+        if data[j] == 1: # 연결된 경우 합집합(Union) 연산 수행
+            union_parent(parent, i + 1, j + 1)
+
+# 여행 계획 입력받기
+plan = list(map(int, input().split()))
+
+result = True
+# 여행 계획에 속하는 모든 노드의 루트가 동일한지 확인
+for i in range(m - 1):
+    if find_parent(parent, plan[i]) != find_parent(parent, plan[i + 1]):
+        result = False
+
+# 여행 계획에 속하는 모든 노드가 서로 연결되어 있는지(루트가 동일한지) 확인
+if result:
+    print("YES")
+else:
+    print("NO")
diff --git a/18/2.cpp b/18/2.cpp
new file mode 100644
index 0000000..714abcb
--- /dev/null
+++ b/18/2.cpp
@@ -0,0 +1,43 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 탑승구의 개수와 비행기의 개수
+int g, p;
+int parent[100001]; // 부모 테이블 초기화
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return parent[x] = findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> g >> p;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= g; i++) {
+        parent[i] = i;
+    }
+
+    int result = 0;
+    for (int i = 0; i < p; i++) {
+        int x;
+        cin >> x;
+        int root = findParent(x); // 현재 비행기의 탑승구의 루트 확인
+        if (root == 0) break; // 현재 루트가 0이라면, 종료
+        unionParent(root, root - 1); // 그렇지 않다면 바로 왼쪽의 집합과 합치기
+        result += 1;
+    }
+
+    cout << result << '\n';
+}
\ No newline at end of file
diff --git a/18/2.java b/18/2.java
new file mode 100644
index 0000000..a5809e5
--- /dev/null
+++ b/18/2.java
@@ -0,0 +1,46 @@
+import java.util.*;
+
+public class Main {
+
+    // 탑승구의 개수와 비행기의 개수
+    public static int g, p;
+    public static int[] parent = new int[100001]; // 부모 테이블 초기화
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return parent[x] = findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        g = sc.nextInt();
+        p = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= g; i++) {
+            parent[i] = i;
+        }
+
+        int result = 0;
+        for (int i = 0; i < p; i++) {
+            int x = sc.nextInt();
+            int root = findParent(x); // 현재 비행기의 탑승구의 루트 확인
+            if (root == 0) break; // 현재 루트가 0이라면, 종료
+            unionParent(root, root - 1); // 그렇지 않다면 바로 왼쪽의 집합과 합치기
+            result += 1;
+        }
+
+        System.out.println(result);
+    }
+}
\ No newline at end of file
diff --git a/18/2.py b/18/2.py
new file mode 100644
index 0000000..c525c02
--- /dev/null
+++ b/18/2.py
@@ -0,0 +1,35 @@
+# 특정 원소가 속한 집합을 찾기
+def find_parent(parent, x):
+    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if parent[x] != x:
+        parent[x] = find_parent(parent, parent[x])
+    return parent[x]
+
+# 두 원소가 속한 집합을 합치기
+def union_parent(parent, a, b):
+    a = find_parent(parent, a)
+    b = find_parent(parent, b)
+    if a < b:
+        parent[b] = a
+    else:
+        parent[a] = b
+
+# 탑승구의 개수 입력받기
+g = int(input())
+# 비행기의 개수 입력받기
+p = int(input())
+parent = [0] * (g + 1) # 부모 테이블 초기화
+
+# 부모 테이블상에서, 부모를 자기 자신으로 초기화
+for i in range(1, g + 1):
+    parent[i] = i
+
+result = 0
+for _ in range(p):
+    data = find_parent(parent, int(input())) # 현재 비행기의 탑승구의 루트 확인
+    if data == 0: # 현재 루트가 0이라면, 종료
+        break
+    union_parent(parent, data, data - 1) # 그렇지 않다면 바로 왼쪽의 집합과 합치기
+    result += 1
+
+print(result)
diff --git a/18/3.cpp b/18/3.cpp
new file mode 100644
index 0000000..6c1c34f
--- /dev/null
+++ b/18/3.cpp
@@ -0,0 +1,61 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수와 간선의 개수
+int n, m;
+int parent[200001]; // 부모 테이블 초기화
+// 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+vector<pair<int, pair<int, int> > > edges;
+int result;
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return parent[x] = findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> n >> m;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= n; i++) {
+        parent[i] = i;
+    }
+
+    // 모든 간선에 대한 정보를 입력받기
+    for (int i = 0; i < m; i++) {
+        int x, y, z;
+        cin >> x >> y >> z;
+        // 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
+        edges.push_back({z, {x, y}});
+    }
+
+    // 간선을 비용순으로 정렬
+    sort(edges.begin(), edges.end());
+    int total = 0; // 전체 가로등 비용
+
+    // 간선을 하나씩 확인하며
+    for (int i = 0; i < edges.size(); i++) {
+        int cost = edges[i].first;
+        int a = edges[i].second.first;
+        int b = edges[i].second.second;
+        total += cost;
+        // 사이클이 발생하지 않는 경우에만 집합에 포함
+        if (findParent(a) != findParent(b)) {
+            unionParent(a, b);
+            result += cost;
+        }
+    }
+
+    cout << total - result << '\n';
+}
\ No newline at end of file
diff --git a/18/3.java b/18/3.java
new file mode 100644
index 0000000..010262f
--- /dev/null
+++ b/18/3.java
@@ -0,0 +1,99 @@
+import java.util.*;
+
+class Edge implements Comparable<Edge> {
+
+    private int distance;
+    private int nodeA;
+    private int nodeB;
+
+    public Edge(int distance, int nodeA, int nodeB) {
+        this.distance = distance;
+        this.nodeA = nodeA;
+        this.nodeB = nodeB;
+    }
+
+    public int getDistance() {
+        return this.distance;
+    }
+
+    public int getNodeA() {
+        return this.nodeA;
+    }
+
+    public int getNodeB() {
+        return this.nodeB;
+    }
+
+    // 거리(비용)가 짧은 것이 높은 우선순위를 가지도록 설정
+    @Override
+    public int compareTo(Edge other) {
+        if (this.distance < other.distance) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+
+    // 노드의 개수와 간선의 개수
+    public static int n, m;
+    public static int[] parent = new int[200001]; // 부모 테이블 초기화하기
+    // 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+    public static ArrayList<Edge> edges = new ArrayList<>();
+    public static int result = 0;
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return parent[x] = findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= n; i++) {
+            parent[i] = i;
+        }
+
+        // 모든 간선에 대한 정보를 입력 받기
+        for (int i = 0; i < m; i++) {
+            int x = sc.nextInt();
+            int y = sc.nextInt();
+            int z = sc.nextInt();
+            edges.add(new Edge(z, x, y));
+        }
+
+        // 간선을 비용순으로 정렬
+        Collections.sort(edges);
+        int total = 0; // 전체 가로등 비용
+
+        // 간선을 하나씩 확인하며
+        for (int i = 0; i < edges.size(); i++) {
+            int cost = edges.get(i).getDistance();
+            int a = edges.get(i).getNodeA();
+            int b = edges.get(i).getNodeB();
+            total += cost;
+            // 사이클이 발생하지 않는 경우에만 집합에 포함
+            if (findParent(a) != findParent(b)) {
+                unionParent(a, b);
+                result += cost;
+            }
+        }
+
+        System.out.println(total - result);
+    }
+}
\ No newline at end of file
diff --git a/18/3.py b/18/3.py
new file mode 100644
index 0000000..1dcb14c
--- /dev/null
+++ b/18/3.py
@@ -0,0 +1,48 @@
+# 특정 원소가 속한 집합을 찾기
+def find_parent(parent, x):
+    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if parent[x] != x:
+        parent[x] = find_parent(parent, parent[x])
+    return parent[x]
+ 
+# 두 원소가 속한 집합을 합치기
+def union_parent(parent, a, b):
+    a = find_parent(parent, a)
+    b = find_parent(parent, b)
+    if a < b:
+        parent[b] = a
+    else:
+        parent[a] = b
+ 
+# 노드의 개수와 간선의 개수 입력받기
+n, m = map(int, input().split())
+parent = [0] * (n + 1) # 부모 테이블 초기화
+
+# 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+edges = []
+result = 0
+
+# 부모 테이블상에서, 부모를 자기 자신으로 초기화
+for i in range(1, n + 1):
+    parent[i] = i
+
+# 모든 간선에 대한 정보를 입력받기
+for _ in range(m):
+    x, y, z = map(int, input().split())
+    # 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
+    edges.append((z, x, y))
+
+# 간선을 비용순으로 정렬
+edges.sort()
+total = 0 # 전체 가로등 비용
+
+# 간선을 하나씩 확인하며
+for edge in edges:
+    cost, a, b = edge
+    total += cost
+    # 사이클이 발생하지 않는 경우에만 집합에 포함
+    if find_parent(parent, a) != find_parent(parent, b):
+        union_parent(parent, a, b)
+        result += cost
+
+print(total - result)
diff --git a/18/4.cpp b/18/4.cpp
new file mode 100644
index 0000000..1e499f7
--- /dev/null
+++ b/18/4.cpp
@@ -0,0 +1,76 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 노드의 개수
+int n;
+int parent[100001]; // 부모 테이블 초기화
+// 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+vector<pair<int, pair<int, int> > > edges;
+int result;
+
+// 특정 원소가 속한 집합을 찾기
+int findParent(int x) {
+    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if (x == parent[x]) return x;
+    return parent[x] = findParent(parent[x]);
+}
+
+// 두 원소가 속한 집합을 합치기
+void unionParent(int a, int b) {
+    a = findParent(a);
+    b = findParent(b);
+    if (a < b) parent[b] = a;
+    else parent[a] = b;
+}
+
+int main(void) {
+    cin >> n;
+
+    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+    for (int i = 1; i <= n; i++) {
+        parent[i] = i;
+    }
+
+    vector<pair<int, int> > x;
+    vector<pair<int, int> > y;
+    vector<pair<int, int> > z;
+
+    // 모든 노드에 대한 좌표 값 입력받기
+    for (int i = 1; i <= n; i++) {
+        int a, b, c;
+        cin >> a >> b >> c;
+        x.push_back({a, i});
+        y.push_back({b, i});
+        z.push_back({c, i});
+    }
+
+    sort(x.begin(), x.end());
+    sort(y.begin(), y.end());
+    sort(z.begin(), z.end());
+
+    // 인접한 노드들로부터 간선 정보를 추출하여 처리
+    for (int i = 0; i < n - 1; i++) {
+        // 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
+        edges.push_back({x[i + 1].first - x[i].first, {x[i].second, x[i + 1].second}});
+        edges.push_back({y[i + 1].first - y[i].first, {y[i].second, y[i + 1].second}});
+        edges.push_back({z[i + 1].first - z[i].first, {z[i].second, z[i + 1].second}});
+    }
+
+    // 간선을 비용순으로 정렬
+    sort(edges.begin(), edges.end());
+
+    // 간선을 하나씩 확인하며
+    for (int i = 0; i < edges.size(); i++) {
+        int cost = edges[i].first;
+        int a = edges[i].second.first;
+        int b = edges[i].second.second;
+        // 사이클이 발생하지 않는 경우에만 집합에 포함
+        if (findParent(a) != findParent(b)) {
+            unionParent(a, b);
+            result += cost;
+        }
+    }
+
+    cout << result << '\n';
+}
\ No newline at end of file
diff --git a/18/4.java b/18/4.java
new file mode 100644
index 0000000..0906f81
--- /dev/null
+++ b/18/4.java
@@ -0,0 +1,141 @@
+import java.util.*;
+
+class Edge implements Comparable<Edge> {
+
+    private int distance;
+    private int nodeA;
+    private int nodeB;
+
+    public Edge(int distance, int nodeA, int nodeB) {
+        this.distance = distance;
+        this.nodeA = nodeA;
+        this.nodeB = nodeB;
+    }
+
+    public int getDistance() {
+        return this.distance;
+    }
+
+    public int getNodeA() {
+        return this.nodeA;
+    }
+
+    public int getNodeB() {
+        return this.nodeB;
+    }
+
+    // 거리(비용)가 짧은 것이 높은 우선순위를 가지도록 설정
+    @Override
+    public int compareTo(Edge other) {
+        if (this.distance < other.distance) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+class Position implements Comparable<Position> {
+
+    private int x;
+    private int y;
+
+    public Position(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public int getX() {
+        return this.x;
+    }
+
+    public int getY() {
+        return this.y;
+    }
+
+    // X축, Y축 순서대로 정렬
+    @Override
+    public int compareTo(Position other) {
+        if (this.x == other.x) {
+            return Integer.compare(this.y, other.y);
+        }
+        return Integer.compare(this.x, other.x);
+    }
+}
+
+public class Main {
+
+    // 노드의 개수
+    public static int n;
+    public static int[] parent = new int[100001]; // 부모 테이블 초기화
+    // 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+    public static ArrayList<Edge> edges = new ArrayList<>();
+    public static int result = 0;
+
+    // 특정 원소가 속한 집합을 찾기
+    public static int findParent(int x) {
+        // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+        if (x == parent[x]) return x;
+        return parent[x] = findParent(parent[x]);
+    }
+
+    // 두 원소가 속한 집합을 합치기
+    public static void unionParent(int a, int b) {
+        a = findParent(a);
+        b = findParent(b);
+        if (a < b) parent[b] = a;
+        else parent[a] = b;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+
+        // 부모 테이블상에서, 부모를 자기 자신으로 초기화
+        for (int i = 1; i <= n; i++) {
+            parent[i] = i;
+        }
+
+        ArrayList<Position> x = new ArrayList<Position>();
+        ArrayList<Position> y = new ArrayList<Position>();
+        ArrayList<Position> z = new ArrayList<Position>();
+
+        // 모든 노드에 대한 좌표 값 입력받기
+        for (int i = 1; i <= n; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            int c = sc.nextInt();
+            x.add(new Position(a, i));
+            y.add(new Position(b, i));
+            z.add(new Position(c, i));
+        }
+
+        Collections.sort(x);
+        Collections.sort(y);
+        Collections.sort(z);
+
+        // 인접한 노드들로부터 간선 정보를 추출하여 처리
+        for (int i = 0; i < n - 1; i++) {
+            edges.add(new Edge(x.get(i + 1).getX() - x.get(i).getX(), x.get(i).getY(), x.get(i + 1).getY()));
+            edges.add(new Edge(y.get(i + 1).getX() - y.get(i).getX(), y.get(i).getY(), y.get(i + 1).getY()));
+            edges.add(new Edge(z.get(i + 1).getX() - z.get(i).getX(), z.get(i).getY(), z.get(i + 1).getY()));
+        }
+
+        // 간선을 비용순으로 정렬
+        Collections.sort(edges);
+
+        // 간선을 하나씩 확인하며
+        for (int i = 0; i < edges.size(); i++) {
+            int cost = edges.get(i).getDistance();
+            int a = edges.get(i).getNodeA();
+            int b = edges.get(i).getNodeB();
+            // 사이클이 발생하지 않는 경우에만 집합에 포함
+            if (findParent(a) != findParent(b)) {
+                unionParent(a, b);
+                result += cost;
+            }
+        }
+
+        System.out.println(result);
+    }
+}
\ No newline at end of file
diff --git a/18/4.py b/18/4.py
new file mode 100644
index 0000000..20ec9b8
--- /dev/null
+++ b/18/4.py
@@ -0,0 +1,62 @@
+# 특정 원소가 속한 집합을 찾기
+def find_parent(parent, x):
+    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
+    if parent[x] != x:
+        parent[x] = find_parent(parent, parent[x])
+    return parent[x]
+ 
+# 두 원소가 속한 집합을 합치기
+def union_parent(parent, a, b):
+    a = find_parent(parent, a)
+    b = find_parent(parent, b)
+    if a < b:
+        parent[b] = a
+    else:
+        parent[a] = b
+ 
+# 노드의 개수 입력받기
+n = int(input())
+parent = [0] * (n + 1) # 부모 테이블 초기화
+
+# 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
+edges = []
+result = 0
+
+# 부모 테이블상에서, 부모를 자기 자신으로 초기화
+for i in range(1, n + 1):
+    parent[i] = i
+
+x = []
+y = []
+z = []
+
+# 모든 노드에 대한 좌표 값 입력받기
+for i in range(1, n + 1):
+    data = list(map(int, input().split()))
+    x.append((data[0], i))
+    y.append((data[1], i))
+    z.append((data[2], i))
+
+x.sort()
+y.sort()
+z.sort()
+
+# 인접한 노드들로부터 간선 정보를 추출하여 처리
+for i in range(n - 1):
+    # 비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
+    edges.append((x[i + 1][0] - x[i][0], x[i][1], x[i + 1][1]))
+    edges.append((y[i + 1][0] - y[i][0], y[i][1], y[i + 1][1]))
+    edges.append((z[i + 1][0] - z[i][0], z[i][1], z[i + 1][1]))
+
+# 간선을 비용순으로 정렬
+edges.sort()
+
+# 간선을 하나씩 확인하며
+for edge in edges:
+    cost, a, b = edge
+    # 사이클이 발생하지 않는 경우에만 집합에 포함
+    if find_parent(parent, a) != find_parent(parent, b):
+        union_parent(parent, a, b)
+        result += cost
+
+print(result)
diff --git a/18/5.cpp b/18/5.cpp
new file mode 100644
index 0000000..c54f4da
--- /dev/null
+++ b/18/5.cpp
@@ -0,0 +1,111 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int testCase, n, m;
+// 모든 노드에 대한 진입차수는 0으로 초기화
+int indegree[501];
+// 각 노드에 연결된 간선 정보를 담기 위한 배열 초기화
+bool graph[501][501];
+
+int main(void) {
+    cin >> testCase;
+
+    // 테스트 케이스(Test Case)만큼 반복
+    for (int tc = 0; tc < testCase; tc++) {
+        fill(indegree, indegree + 501, 0);
+        for (int i = 0; i < 501; i++) {
+            fill(graph[i], graph[i] + 501, false);
+        }
+
+        cin >> n;
+        // 작년 순위 정보 입력
+        vector<int> v;
+        for (int i = 0; i < n; i++) {
+            int x;
+            cin >> x;
+            v.push_back(x);
+        }
+        // 방향 그래프의 간선 정보 초기화
+        for (int i = 0; i < n; i++) {
+            for (int j = i + 1; j < n; j++) {
+                graph[v[i]][v[j]] = true;
+                indegree[v[j]] += 1;
+            }
+        }
+
+        // 올해 변경된 순위 정보 입력
+        cin >> m;
+        for (int i = 0; i < m; i++) {
+            int a, b;
+            cin >> a >> b;
+            // 간선의 방향 뒤집기
+            if (graph[a][b]) {
+                graph[a][b] = false;
+                graph[b][a] = true;
+                indegree[a] += 1;
+                indegree[b] -= 1;
+            }
+            else {
+                graph[a][b] = true;
+                graph[b][a] = false;
+                indegree[a] -= 1;
+                indegree[b] += 1;
+            }
+        }
+
+        // 위상 정렬(Topology Sort) 시작
+        vector<int> result; // 알고리즘 수행 결과를 담을 리스트
+        queue<int> q; // 큐 라이브러리 사용
+
+        // 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
+        for (int i = 1; i <= n; i++) {
+            if (indegree[i] == 0) {
+                q.push(i);
+            }
+        }
+
+        bool certain = true; // 위상 정렬 결과가 오직 하나인지의 여부
+        bool cycle = false; // 그래프 내 사이클이 존재하는지 여부
+
+        // 정확히 노드의 개수만큼 반복
+        for (int i = 0; i < n; i++) {
+            // 큐가 비어 있다면 사이클이 발생했다는 의미
+            if (q.size() == 0) {
+                cycle = true;
+                break;
+            }
+            // 큐의 원소가 2개 이상이라면 가능한 정렬 결과가 여러 개라는 의미
+            if (q.size() >= 2) {
+                certain = false;
+                break;
+            }
+            // 큐에서 원소 꺼내기
+            int now = q.front();
+            q.pop();
+            result.push_back(now);
+            // 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
+            for (int j = 1; j <= n; j++) {
+                if (graph[now][j]) {
+                    indegree[j] -= 1;
+                    // 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
+                    if (indegree[j] == 0) {
+                        q.push(j);
+                    }
+                }
+            }
+        }
+
+        // 사이클이 발생하는 경우(일관성이 없는 경우)
+        if (cycle) cout << "IMPOSSIBLE" << '\n';
+        // 위상 정렬 결과가 여러 개인 경우
+        else if (!certain) cout << "?" << '\n';
+        // 위상 정렬을 수행한 결과 출력
+        else {
+            for (int i = 0; i < result.size(); i++) {
+                cout << result[i] << ' ';
+            }
+            cout << '\n';
+        }
+    }
+}
\ No newline at end of file
diff --git a/18/5.java b/18/5.java
new file mode 100644
index 0000000..2cb1f9c
--- /dev/null
+++ b/18/5.java
@@ -0,0 +1,110 @@
+import java.util.*;
+
+public class Main {
+
+    public static int testCase, n, m;
+    // 모든 노드에 대한 진입차수는 0으로 초기화
+    public static int[] indegree = new int[501];
+    // 각 노드에 연결된 간선 정보를 담기 위한 배열 초기화
+    public static boolean[][] graph = new boolean[501][501];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        testCase = sc.nextInt();
+
+        for (int tc = 0; tc < testCase; tc++) {
+            Arrays.fill(indegree, 0);
+            for (int i = 0; i < 501; i++) {
+                Arrays.fill(graph[i], false);
+            }
+
+            n = sc.nextInt();
+            // 작년 순위 정보 입력
+            ArrayList<Integer> arrayList = new ArrayList<>();
+            for (int i = 0; i < n; i++) {
+                int x = sc.nextInt();
+                arrayList.add(x);
+            }
+            // 방향 그래프의 간선 정보 초기화
+            for (int i = 0; i < n; i++) {
+                for (int j = i + 1; j < n; j++) {
+                    graph[arrayList.get(i)][arrayList.get(j)] = true;
+                    indegree[arrayList.get(j)] += 1;
+                }
+            }
+
+            // 올해 변경된 순위 정보 입력
+            m = sc.nextInt();
+            for (int i = 0; i < m; i++) {
+                int a = sc.nextInt();
+                int b = sc.nextInt();
+                // 간선의 방향 뒤집기
+                if (graph[a][b]) {
+                    graph[a][b] = false;
+                    graph[b][a] = true;
+                    indegree[a] += 1;
+                    indegree[b] -= 1;
+                }
+                else {
+                    graph[a][b] = true;
+                    graph[b][a] = false;
+                    indegree[a] -= 1;
+                    indegree[b] += 1;
+                }
+            }
+
+            // 위상 정렬(Topology Sort) 시작
+            ArrayList<Integer> result = new ArrayList<>(); // 알고리즘 수행 결과를 담을 리스트
+            Queue<Integer> q = new LinkedList<>(); // 큐 라이브러리 사용
+
+            // 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
+            for (int i = 1; i <= arrayList.size(); i++) {
+                if (indegree[i] == 0) {
+                    q.offer(i);
+                }
+            }
+
+            boolean certain = true; // 위상 정렬 결과가 오직 하나인지의 여부
+            boolean cycle = false; // 그래프 내 사이클이 존재하는지 여부
+
+            // 정확히 노드의 개수만큼 반복
+            for (int i = 0; i < n; i++) {
+                // 큐가 비어 있다면 사이클이 발생했다는 의미
+                if (q.size() == 0) {
+                    cycle = true;
+                    break;
+                }
+                // 큐의 원소가 2개 이상이라면 가능한 정렬 결과가 여러 개라는 의미
+                if (q.size() >= 2) {
+                    certain = false;
+                    break;
+                }
+                // 큐에서 원소 꺼내기
+                int now = q.poll();
+                result.add(now);
+                // 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
+                for (int j = 1; j <= n; j++) {
+                    if (graph[now][j]) {
+                        indegree[j] -= 1;
+                        // 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
+                        if (indegree[j] == 0) {
+                            q.offer(j);
+                        }
+                    }
+                }
+            }
+
+            // 사이클이 발생하는 경우(일관성이 없는 경우)
+            if (cycle) System.out.println("IMPOSSIBLE");
+            // 위상 정렬 결과가 여러 개인 경우
+            else if (!certain) System.out.println("?");
+            // 위상 정렬을 수행한 결과 출력
+            else {
+                for (int i = 0; i < result.size(); i++) {
+                    System.out.print(result.get(i) + " ");
+                }
+                System.out.println();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/18/5.py b/18/5.py
new file mode 100644
index 0000000..2187a93
--- /dev/null
+++ b/18/5.py
@@ -0,0 +1,79 @@
+from collections import deque
+
+# 테스트 케이스(Test Case)만큼 반복
+for tc in range(int(input())):
+    # 노드의 개수 입력 받기
+    n = int(input())
+    # 모든 노드에 대한 진입차수는 0으로 초기화
+    indegree = [0] * (n + 1)
+    # 각 노드에 연결된 간선 정보를 담기 위한 인접 행렬 초기화
+    graph = [[False] * (n + 1) for i in range(n + 1)]
+
+    # 작년 순위 정보 입력
+    data = list(map(int, input().split()))
+    # 방향 그래프의 간선 정보 초기화
+    for i in range(n):
+        for j in range(i + 1, n):
+            graph[data[i]][data[j]] = True
+            indegree[data[j]] += 1
+
+    # 올해 변경된 순위 정보 입력
+    m = int(input())
+    for i in range(m):
+        a, b = map(int, input().split())
+        # 간선의 방향 뒤집기
+        if graph[a][b]:
+            graph[a][b] = False
+            graph[b][a] = True
+            indegree[a] += 1
+            indegree[b] -= 1
+        else:
+            graph[a][b] = True
+            graph[b][a] = False
+            indegree[a] -= 1
+            indegree[b] += 1
+
+    # 위상 정렬(Topology Sort) 시작
+    result = [] # 알고리즘 수행 결과를 담을 리스트
+    q = deque() # 큐 기능을 위한 deque 라이브러리 사용
+
+    # 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
+    for i in range(1, n + 1):
+        if indegree[i] == 0:
+            q.append(i)
+
+    certain = True # 위상 정렬 결과가 오직 하나인지의 여부
+    cycle = False # 그래프 내 사이클이 존재하는지 여부
+
+    # 정확히 노드의 개수만큼 반복
+    for i in range(n):
+        # 큐가 비어 있다면 사이클이 발생했다는 의미
+        if len(q) == 0:
+            cycle = True
+            break
+        # 큐의 원소가 2개 이상이라면 가능한 정렬 결과가 여러 개라는 의미
+        if len(q) >= 2:
+            certain = False
+            break
+        # 큐에서 원소 꺼내기
+        now = q.popleft()
+        result.append(now)
+        # 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
+        for j in range(1, n + 1):
+            if graph[now][j]:
+                indegree[j] -= 1
+                # 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
+                if indegree[j] == 0:
+                    q.append(j)
+
+    # 사이클이 발생하는 경우(일관성이 없는 경우)
+    if cycle:
+        print("IMPOSSIBLE")
+    # 위상 정렬 결과가 여러 개인 경우
+    elif not certain:
+        print("?")
+    # 위상 정렬을 수행한 결과 출력
+    else:
+        for i in result:
+            print(i, end=' ')
+        print()
diff --git a/19/1.py b/19/1.py
new file mode 100644
index 0000000..8f23b63
--- /dev/null
+++ b/19/1.py
@@ -0,0 +1,83 @@
+from collections import deque
+INF = 1e9 # 무한을 의미하는 값으로 10억을 설정
+
+# 맵의 크기 N 입력
+n = int(input())
+
+# 전체 모든 칸에 대한 정보 입력
+array = []
+for i in range(n):
+    array.append(list(map(int, input().split())))
+
+# 아기 상어의 현재 크기 변수와 현재 위치 변수
+now_size = 2
+now_x, now_y = 0, 0
+
+# 아기 상어의 시작 위치를 찾은 뒤에 그 위치엔 아무것도 없다고 처리
+for i in range(n):
+    for j in range(n):
+        if array[i][j] == 9:
+            now_x, now_y = i, j
+            array[now_x][now_y] = 0
+
+dx = [-1, 0, 1, 0]
+dy = [0, 1, 0, -1]
+
+# 모든 위치까지의 '최단 거리만' 계산하는 BFS 함수
+def bfs():
+    # 값이 -1이라면 도달할 수 없다는 의미 (초기화)
+    dist = [[-1] * n for _ in range(n)]
+    # 시작 위치는 도달이 가능하다고 보며 거리는 0
+    q = deque([(now_x, now_y)])
+    dist[now_x][now_y] = 0
+    while q:
+        x, y = q.popleft()
+        for i in range(4):
+            nx = x + dx[i]
+            ny = y + dy[i]
+            if 0 <= nx and nx < n and 0 <= ny and ny < n:
+                # 자신의 크기보다 작거나 같은 경우에 지나갈 수 있음
+                if dist[nx][ny] == -1 and array[nx][ny] <= now_size:
+                    dist[nx][ny] = dist[x][y] + 1
+                    q.append((nx, ny))
+    # 모든 위치까지의 최단 거리 테이블 반환
+    return dist
+
+# 최단 거리 테이블이 주어졌을 때, 먹을 물고기를 찾는 함수
+def find(dist):
+    x, y = 0, 0
+    min_dist = INF
+    for i in range(n):
+        for j in range(n):
+            # 도달이 가능하면서 먹을 수 있는 물고기일 때
+            if dist[i][j] != -1 and 1 <= array[i][j] and array[i][j] < now_size:
+                # 가장 가까운 물고기 한 마리만 선택
+                if dist[i][j] < min_dist:
+                    x, y = i, j
+                    min_dist = dist[i][j]
+    if min_dist == INF: # 먹을 수 있는 물고기가 없는 경우
+        return None
+    else:
+        return x, y, min_dist # 먹을 물고기의 위치와 최단 거리
+
+result = 0 # 최종 답안
+ate = 0 # 현재 크기에서 먹은 양
+
+while True:
+    # 먹을 수 있는 물고기의 위치 찾기
+    value = find(bfs())
+    # 먹을 수 있는 물고기가 없는 경우, 현재까지 움직인 거리 출력
+    if value == None:
+        print(result)
+        break
+    else:
+        # 현재 위치 갱신 및 이동 거리 변경
+        now_x, now_y = value[0], value[1]
+        result += value[2]
+        # 먹은 위치에는 이제 아무것도 없도록 처리
+        array[now_x][now_y] = 0
+        ate += 1
+        # 자신의 현재 크기 이상으로 먹은 경우, 크기 증가
+        if ate >= now_size:
+            now_size += 1
+            ate = 0
diff --git a/19/2.py b/19/2.py
new file mode 100644
index 0000000..80cf0d7
--- /dev/null
+++ b/19/2.py
@@ -0,0 +1,89 @@
+import copy
+
+# 4 X 4 크기 격자에 존재하는 각 물고기의 번호(없으면 -1)와 방향 값을 담는 테이블
+array = [[None] * 4 for _ in range(4)]
+
+for i in range(4):
+    data = list(map(int, input().split()))
+    # 매 줄마다 4마리의 물고기를 하나씩 확인하며
+    for j in range(4):
+        # 각 위치마다 [물고기의 번호, 방향]을 저장
+        array[i][j] = [data[j * 2], data[j * 2 + 1] - 1]
+
+# 8가지 방향에 대한 정의
+dx = [-1, -1, 0, 1, 1, 1, 0, -1]
+dy = [0, -1, -1, -1, 0, 1, 1, 1]
+
+# 현재 위치에서 왼쪽으로 회전된 결과 반환
+def turn_left(direction):
+    return (direction + 1) % 8
+
+result = 0 # 최종 결과
+
+# 현재 배열에서 특정한 번호의 물고기 위치 찾기
+def find_fish(array, index):
+    for i in range(4):
+        for j in range(4):
+            if array[i][j][0] == index:
+                return (i, j)
+    return None
+
+# 모든 물고기를 회전 및 이동시키는 함수
+def move_all_fishes(array, now_x, now_y):
+    # 1번부터 16번까지의 물고기를 차례대로 (낮은 번호부터) 확인
+    for i in range(1, 17):
+        # 해당 물고기의 위치를 찾기
+        position = find_fish(array, i)
+        if position != None:
+            x, y = position[0], position[1]
+            direction = array[x][y][1]
+            # 해당 물고기의 방향을 왼쪽으로 계속 회전시키며 이동이 가능한지 확인
+            for j in range(8):
+                nx = x + dx[direction]
+                ny = y + dy[direction]
+                # 해당 방향으로 이동이 가능하다면 이동 시키기
+                if 0 <= nx and nx < 4 and 0 <= ny and ny < 4:
+                    if not (nx == now_x and ny == now_y):
+                        array[x][y][1] = direction
+                        array[x][y], array[nx][ny] = array[nx][ny], array[x][y]
+                        break
+                direction = turn_left(direction)
+        
+# 상어가 현재 위치에서 먹을 수 있는 모든 물고기의 위치 반환
+def get_possible_positions(array, now_x, now_y):
+    positions = []
+    direction = array[now_x][now_y][1]
+    # 현재의 방향으로 쭉 이동하기
+    for i in range(4):
+        now_x += dx[direction]
+        now_y += dy[direction]
+        # 범위를 벗어나지 않는지 확인하며
+        if 0 <= now_x and now_x < 4 and 0 <= now_y and now_y < 4:
+            # 물고기가 존재하는 경우
+            if array[now_x][now_y][0] != -1:
+                positions.append((now_x, now_y))
+    return positions
+
+# 모든 경우를 탐색하기 위한 DFS 함수
+def dfs(array, now_x, now_y, total):
+    global result
+    array = copy.deepcopy(array) # 리스트를 통째로 복사
+    
+    total += array[now_x][now_y][0] # 현재 위치의 물고기 먹기
+    array[now_x][now_y][0] = -1 # 물고기를 먹었으므로 번호 값을 -1로 변환
+    
+    move_all_fishes(array, now_x, now_y) # 전체 물고기 이동 시키기
+
+    # 이제 다시 상어가 이동할 차례이므로, 이동 가능한 위치 찾기
+    positions = get_possible_positions(array, now_x, now_y)
+    # 이동할 수 있는 위치가 하나도 없다면 종료
+    if len(positions) == 0:
+        result = max(result, total) # 최댓값 저장
+        return 
+    # 모든 이동할 수 있는 위치로 재귀적으로 수행
+    for next_x, next_y in positions:
+        dfs(array, next_x, next_y, total)
+
+# 청소년 상어의 시작 위치(0, 0)에서부터 재귀적으로 모든 경우 탐색
+dfs(array, 0, 0, 0)
+print(result)
diff --git a/19/3.py b/19/3.py
new file mode 100644
index 0000000..bcdfa92
--- /dev/null
+++ b/19/3.py
@@ -0,0 +1,97 @@
+n, m, k = map(int, input().split())
+
+# 모든 상어의 위치와 방향 정보를 포함하는 2차원 리스트
+array = []
+for i in range(n):
+    array.append(list(map(int, input().split())))
+
+# 모든 상어의 현재 방향 정보
+directions = list(map(int, input().split()))
+
+# 각 위치마다 [특정 냄새의 상어 번호, 특정 냄새의 남은 시간]을 저장하는 2차원 리스트
+smell = [[[0, 0]] * n for _ in range(n)]
+
+# 각 상어의 회전 우선순위 정보
+priorities = [[] for _ in range(m)]
+for i in range(m):
+    for j in range(4):
+        priorities[i].append(list(map(int, input().split())))
+
+# 특정 위치에서 이동 가능한 4가지 방향
+dx = [-1, 1, 0, 0]
+dy = [0, 0, -1, 1]
+
+# 모든 냄새 정보를 업데이트
+def update_smell():
+    # 각 위치를 하나씩 확인하며
+    for i in range(n):
+        for j in range(n):
+            # 냄새가 존재하는 경우, 시간을 1만큼 감소시키기
+            if smell[i][j][1] > 0:
+                smell[i][j][1] -= 1
+            # 상어가 존재하는 해당 위치의 냄새를 k로 설정
+            if array[i][j] != 0:
+                smell[i][j] = [array[i][j], k]
+
+# 모든 상어를 이동시키는 함수
+def move():
+    # 이동 결과를 담기 위한 임시 결과 테이블 초기화
+    new_array = [[0] * n for _ in range(n)]
+    # 각 위치를 하나씩 확인하며
+    for x in range(n):
+        for y in range(n):
+            # 상어가 존재하는 경우
+            if array[x][y] != 0:
+                direction = directions[array[x][y] - 1] # 현재 상어의 방향
+                found = False
+                # 일단 냄새가 존재하지 않는 곳이 있는지 확인
+                for index in range(4):
+                    nx = x + dx[priorities[array[x][y] - 1][direction - 1][index] - 1]
+                    ny = y + dy[priorities[array[x][y] - 1][direction - 1][index] - 1]
+                    if 0 <= nx and nx < n and 0 <= ny and ny < n:
+                        if smell[nx][ny][1] == 0: # 냄새가 존재하지 않는 곳이면
+                            # 해당 상어의 방향 이동시키기
+                            directions[array[x][y] - 1] = priorities[array[x][y] - 1][direction - 1][index]
+                            # 상어 이동시키기 (만약 이미 다른 상어가 있다면 번호가 낮은 것이 들어가도록)
+                            if new_array[nx][ny] == 0:
+                                new_array[nx][ny] = array[x][y]
+                            else:
+                                new_array[nx][ny] = min(new_array[nx][ny], array[x][y])
+                            found = True
+                            break
+                if found:
+                    continue
+                # 주변에 모두 냄새가 남아 있다면, 자신의 냄새가 있는 곳으로 이동
+                for index in range(4):
+                    nx = x + dx[priorities[array[x][y] - 1][direction - 1][index] - 1]
+                    ny = y + dy[priorities[array[x][y] - 1][direction - 1][index] - 1]
+                    if 0 <= nx and nx < n and 0 <= ny and ny < n:
+                        if smell[nx][ny][0] == array[x][y]: # 자신의 냄새가 있는 곳이면
+                            # 해당 상어의 방향 이동시키기
+                            directions[array[x][y] - 1] = priorities[array[x][y] - 1][direction - 1][index]
+                            # 상어 이동시키기
+                            new_array[nx][ny] = array[x][y]
+                            break
+    return new_array
+
+time = 0
+while True:
+    update_smell() # 모든 위치의 냄새를 업데이트
+    new_array = move() # 모든 상어를 이동시키기
+    array = new_array # 맵 업데이트
+    time += 1 # 시간 증가
+
+    # 1번 상어만 남았는지 체크
+    check = True
+    for i in range(n):
+        for j in range(n):
+            if array[i][j] > 1:
+                check = False
+    if check:
+        print(time)
+        break
+
+    # 1000초가 지날 때까지 끝나지 않았다면
+    if time >= 1000:
+        print(-1)
+        break
diff --git a/20/1.cpp b/20/1.cpp
new file mode 100644
index 0000000..58aeb84
--- /dev/null
+++ b/20/1.cpp
@@ -0,0 +1,20 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 소수 판별 함수(2이상의 자연수에 대하여)
+bool isPrimeNumber(int x) {
+    // 2부터 x의 제곱근까지의 모든 수를 확인하며
+    for (int i = 2; i <= (int) sqrt(x); i++) {
+        // x가 해당 수로 나누어떨어진다면
+        if (x % i == 0) {
+            return false; // 소수가 아님
+        }
+    }
+    return true; // 소수임
+}
+
+int main() {
+    cout << isPrimeNumber(4) << '\n';
+    cout << isPrimeNumber(7) << '\n';
+}
diff --git a/20/1.java b/20/1.java
new file mode 100644
index 0000000..34e1865
--- /dev/null
+++ b/20/1.java
@@ -0,0 +1,20 @@
+import java.util.*;
+
+class Main {
+    // 소수 판별 함수(2이상의 자연수에 대하여)
+    public static boolean isPrimeNumber(int x) {
+        // 2부터 x의 제곱근까지의 모든 수를 확인하며
+        for (int i = 2; i <= Math.sqrt(x); i++) {
+            // x가 해당 수로 나누어떨어진다면
+            if (x % i == 0) {
+                return false; // 소수가 아님
+            }
+        }
+        return true; // 소수임
+    }
+
+    public static void main(String[] args) {
+        System.out.println(isPrimeNumber(4));
+        System.out.println(isPrimeNumber(7));
+    }
+}
diff --git a/20/1.py b/20/1.py
new file mode 100644
index 0000000..313580d
--- /dev/null
+++ b/20/1.py
@@ -0,0 +1,13 @@
+import math
+
+# 소수 판별 함수
+def is_prime_number(x):
+    # 2부터 x의 제곱근까지의 모든 수를 확인하며
+    for i in range(2, int(math.sqrt(x)) + 1):
+        # x가 해당 수로 나누어떨어진다면
+        if x % i == 0:
+            return False # 소수가 아님
+    return True # 소수임
+
+print(is_prime_number(4)) # 4는 소수가 아님
+print(is_prime_number(7)) # 7은 소수임
diff --git a/20/2.cpp b/20/2.cpp
new file mode 100644
index 0000000..07be191
--- /dev/null
+++ b/20/2.cpp
@@ -0,0 +1,27 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n = 1000; // 2부터 1,000까지의 모든 수에 대하여 소수 판별
+// 처음엔 모든 수가 소수(True)인 것으로 초기화(0과 1은 제외)
+vector<int> arr(n + 1, true);
+
+int main() {
+    // 에라토스테네스의 체 알고리즘 수행
+    // 2부터 n의 제곱근까지의 모든 수를 확인하며
+    for (int i = 2; i <= (int) sqrt(n); i++) {
+        // i가 소수인 경우(남은 수인 경우)
+        if (arr[i] == true) {
+            // i를 제외한 i의 모든 배수를 지우기
+            int j = 2;
+            while (i * j <= n) {
+                arr[i * j] = false;
+                j += 1;
+            }
+        }
+    }
+    // 모든 소수 출력
+    for (int i = 2; i <= n; i++) {
+        if (arr[i]) cout << i << ' ';
+    }
+}
diff --git a/20/2.java b/20/2.java
new file mode 100644
index 0000000..71b2dde
--- /dev/null
+++ b/20/2.java
@@ -0,0 +1,27 @@
+import java.util.*;
+
+class Main {
+    public static int n = 1000; // 2부터 1,000까지의 모든 수에 대하여 소수 판별
+    public static boolean[] arr = new boolean[n + 1];
+
+    public static void main(String[] args) {
+        Arrays.fill(arr, true); // 처음엔 모든 수가 소수(True)인 것으로 초기화(0과 1은 제외)
+        // 에라토스테네스의 체 알고리즘 수행
+        // 2부터 n의 제곱근까지의 모든 수를 확인하며
+        for (int i = 2; i <= Math.sqrt(n); i++) {
+            // i가 소수인 경우(남은 수인 경우)
+            if (arr[i] == true) {
+                // i를 제외한 i의 모든 배수를 지우기
+                int j = 2;
+                while (i * j <= n) {
+                    arr[i * j] = false;
+                    j += 1;
+                }
+            }
+        }
+        // 모든 소수 출력
+        for (int i = 2; i <= n; i++) {
+            if (arr[i]) System.out.print(i + " ");
+        }
+    }
+}
diff --git a/20/2.py b/20/2.py
new file mode 100644
index 0000000..ff4a117
--- /dev/null
+++ b/20/2.py
@@ -0,0 +1,18 @@
+import math
+
+n = 1000 # 2부터 1,000까지의 모든 수에 대하여 소수 판별
+array = [True for i in range(n + 1)] # 처음엔 모든 수가 소수(True)인 것으로 초기화
+
+# 에라토스테네스의 체 알고리즘 
+for i in range(2, int(math.sqrt(n)) + 1): # 2부터 n의 제곱근까지의 모든 수를 확인하며
+    if array[i] == True: # i가 소수인 경우 (남은 수인 경우)
+        # i를 제외한 i의 모든 배수를 지우기
+        j = 2 
+        while i * j <= n:
+            array[i * j] = False
+            j += 1
+
+# 모든 소수 출력
+for i in range(2, n + 1):
+    if array[i]:
+        print(i, end=' ')
diff --git a/20/3.cpp b/20/3.cpp
new file mode 100644
index 0000000..ecdc566
--- /dev/null
+++ b/20/3.cpp
@@ -0,0 +1,29 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n = 5; // 데이터의 개수 N
+int m = 5; // 찾고자 하는 부분합 M
+int arr[] = {1, 2, 3, 2, 5}; // 전체 수열
+
+int main() {
+    int cnt = 0;
+    int intervalSum = 0;
+    int end = 0;
+
+    // start를 차례대로 증가시키며 반복
+    for (int start = 0; start < n; start++) {
+        // end를 가능한 만큼 이동시키기
+        while (intervalSum < m && end < n) {
+            intervalSum += arr[end];
+            end += 1;
+        }
+        // 부분합이 m일 때 카운트 증가
+        if (intervalSum == m) {
+            cnt += 1;
+        }
+        intervalSum -= arr[start];
+    }
+
+    cout << cnt << '\n';
+}
diff --git a/20/3.java b/20/3.java
new file mode 100644
index 0000000..eb610d4
--- /dev/null
+++ b/20/3.java
@@ -0,0 +1,29 @@
+import java.util.*;
+
+class Main {
+    public static int n = 5; // 데이터의 개수 N
+    public static int m = 5; // 찾고자 하는 부분합 M
+    public static int[] arr = {1, 2, 3, 2, 5}; // 전체 수열
+
+    public static void main(String[] args) {
+        int cnt = 0;
+        int intervalSum = 0;
+        int end = 0;
+
+        // start를 차례대로 증가시키며 반복
+        for (int start = 0; start < n; start++) {
+            // end를 가능한 만큼 이동시키기
+            while (intervalSum < m && end < n) {
+                intervalSum += arr[end];
+                end += 1;
+            }
+            // 부분합이 m일 때 카운트 증가
+            if (intervalSum == m) {
+                cnt += 1;
+            }
+            intervalSum -= arr[start];
+        }
+
+        System.out.println(cnt);
+    }
+}
diff --git a/20/3.py b/20/3.py
new file mode 100644
index 0000000..61b4375
--- /dev/null
+++ b/20/3.py
@@ -0,0 +1,20 @@
+n = 5 # 데이터의 개수 N
+m = 5 # 찾고자 하는 부분합 M
+data = [1, 2, 3, 2, 5] # 전체 수열
+
+count = 0
+interval_sum = 0
+end = 0
+
+# start를 차례대로 증가시키며 반복
+for start in range(n):
+    # end를 가능한 만큼 이동시키기
+    while interval_sum < m and end < n:
+        interval_sum += data[end]
+        end += 1
+    # 부분합이 m일 때 카운트 증가
+    if interval_sum == m:
+        count += 1
+    interval_sum -= data[start]
+
+print(count)
diff --git a/20/4.py b/20/4.py
new file mode 100644
index 0000000..a33f02b
--- /dev/null
+++ b/20/4.py
@@ -0,0 +1,28 @@
+# 사전에 정렬된 리스트 A와 B 선언
+n, m = 3, 4
+a = [1, 3, 5]
+b = [2, 4, 6, 8]
+
+# 리스트 A와 B의 모든 원소를 담을 수 있는 크기의 결과 리스트 초기화
+result = [0] * (n + m)
+i = 0
+j = 0
+k = 0
+
+# 모든 원소가 결과 리스트에 담길 때까지 반복
+while i < n or j < m:
+    # 리스트 B의 모든 원소가 처리되었거나, 리스트 A의 원소가 더 작을 때
+    if j >= m or (i < n and a[i] <= b[j]):
+        # 리스트 A의 원소를 결과 리스트로 옮기기
+        result[k] = a[i]
+        i += 1
+    # 리스트 A의 모든 원소가 처리되었거나, 리스트 B의 원소가 더 작을 때
+    else:
+        # 리스트 B의 원소를 결과 리스트로 옮기기
+        result[k] = b[j]
+        j += 1
+    k += 1
+
+# 결과 리스트 출력
+for i in result:
+    print(i, end=' ')
diff --git a/20/5.cpp b/20/5.cpp
new file mode 100644
index 0000000..fbeaed8
--- /dev/null
+++ b/20/5.cpp
@@ -0,0 +1,22 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n = 5; // 데이터의 개수 N과 데이터 입력받기
+int arr[] = {10, 20, 30, 40, 50};
+int prefixSum[6];
+
+int main() {
+    // 접두사 합(Prefix Sum) 배열 계산
+    int sumValue = 0;
+
+    for (int i = 0; i < n; i++) {
+        sumValue += arr[i];
+        prefixSum[i + 1] = sumValue;
+    }
+
+    // 구간 합 계산(세 번째 수부터 네 번째 수까지)
+    int left = 3;
+    int right = 4;
+    cout << prefixSum[right] - prefixSum[left - 1] << '\n';
+}
diff --git a/20/5.java b/20/5.java
new file mode 100644
index 0000000..a0b2fcc
--- /dev/null
+++ b/20/5.java
@@ -0,0 +1,22 @@
+import java.util.*;
+
+class Main {
+    public static int n = 5; // 데이터의 개수 N과 데이터 입력받기
+    public static int arr[] = {10, 20, 30, 40, 50};
+    public static int[] prefixSum = new int[6];
+
+    public static void main(String[] args) {
+        // 접두사 합(Prefix Sum) 배열 계산
+        int sumValue = 0;
+
+        for (int i = 0; i < n; i++) {
+            sumValue += arr[i];
+            prefixSum[i + 1] = sumValue;
+        }
+
+        // 구간 합 계산(세 번째 수부터 네 번째 수까지)
+        int left = 3;
+        int right = 4;
+        System.out.println(prefixSum[right] - prefixSum[left - 1]);
+    }
+}
diff --git a/20/5.py b/20/5.py
new file mode 100644
index 0000000..d193683
--- /dev/null
+++ b/20/5.py
@@ -0,0 +1,15 @@
+# 데이터의 개수 N과 전체 데이터 선언
+n = 5
+data = [10, 20, 30, 40, 50]
+
+# 접두사 합(Prefix Sum) 배열 계산
+sum_value = 0
+prefix_sum = [0]
+for i in data:
+    sum_value += i
+    prefix_sum.append(sum_value)
+
+# 구간 합 계산 (세 번째 수부터 네 번째 수까지)
+left = 3
+right = 4
+print(prefix_sum[right] - prefix_sum[left - 1])
diff --git a/20/6.py b/20/6.py
new file mode 100644
index 0000000..ce0d049
--- /dev/null
+++ b/20/6.py
@@ -0,0 +1,6 @@
+import itertools
+
+data = [1, 2, 3]
+
+for x in itertools.permutations(data, 2):
+    print(list(x), end=' ')
diff --git a/20/7.py b/20/7.py
new file mode 100644
index 0000000..0a39b08
--- /dev/null
+++ b/20/7.py
@@ -0,0 +1,6 @@
+import itertools
+
+data = [1, 2, 3]
+
+for x in itertools.combinations(data, 2):
+    print(list(x), end=' ')
diff --git a/20/8.py b/20/8.py
new file mode 100644
index 0000000..7036a81
--- /dev/null
+++ b/20/8.py
@@ -0,0 +1,20 @@
+import math
+
+# M과 N을 입력받기
+m, n = map(int, input().split())
+array = [True for i in range(1000001)] # 처음엔 모든 수가 소수(True)인 것으로 초기화
+array[1] = 0 # 1은 소수가 아님
+
+# 에라토스테네스의 체 알고리즘 
+for i in range(2, int(math.sqrt(n)) + 1): # 2부터 n의 제곱근까지의 모든 수를 확인하며
+    if array[i] == True: # i가 소수인 경우 (남은 수인 경우)
+        # i를 제외한 i의 모든 배수를 지우기
+        j = 2 
+        while i * j <= n:
+            array[i * j] = False
+            j += 1
+
+# m부터 n까지의 모든 소수 출력
+for i in range(m, n + 1):
+    if array[i]:
+        print(i)
diff --git a/20/9.py b/20/9.py
new file mode 100644
index 0000000..f4d5470
--- /dev/null
+++ b/20/9.py
@@ -0,0 +1,19 @@
+from itertools import combinations
+
+vowels = ('a', 'e', 'i', 'o', 'u') # 5개의 모음 정의
+l, c = map(int, input().split(' '))
+
+# 가능한 암호를 사전식으로 출력해야 하므로 입력 이후에 정렬 수행
+array = input().split(' ')
+array.sort()
+
+# 길이가 l인 모든 암호 조합을 확인
+for password in combinations(array, l):
+    # 패스워드에 포함된 각 문자를 확인하며 모음의 개수를 세기
+    count = 0
+    for i in password:
+        if i in vowels:
+            count += 1
+    # 최소 1개의 모음과 최소 2개의 자음이 있는 경우 출력
+    if count >= 1 and count <= l - 2:
+        print(''.join(password))
diff --git a/21/1.py b/21/1.py
new file mode 100644
index 0000000..db6f7b7
--- /dev/null
+++ b/21/1.py
@@ -0,0 +1,63 @@
+class Node:
+    def __init__(self, data, left_node, right_node):
+        self.data = data
+        self.left_node = left_node
+        self.right_node = right_node
+
+# 전위 순회(Preorder Traversal)
+def pre_order(node):
+    print(node.data, end=' ')
+    if node.left_node != None:
+        pre_order(tree[node.left_node])
+    if node.right_node != None:
+        pre_order(tree[node.right_node])
+
+# 중위 순회(Inorder Traversal)
+def in_order(node):
+    if node.left_node != None:
+        in_order(tree[node.left_node])
+    print(node.data, end=' ')
+    if node.right_node != None:
+        in_order(tree[node.right_node])
+
+# 후위 순회(Postorder Traversal)
+def post_order(node):
+    if node.left_node != None:
+        post_order(tree[node.left_node])
+    if node.right_node != None:
+        post_order(tree[node.right_node])
+    print(node.data, end=' ')
+
+n = int(input())
+tree = {}
+
+for i in range(n):
+    data, left_node, right_node = input().split()
+    if left_node == "None":
+        left_node = None
+    if right_node == "None":
+        right_node = None
+    tree[data] = Node(data, left_node, right_node)
+
+pre_order(tree['A'])
+print()
+in_order(tree['A'])
+print()
+post_order(tree['A'])
+
+'''
+[예시 입력]
+7
+A B C
+B D E
+C F G
+D None None
+E None None
+F None None
+G None None
+
+[예시 출력]
+A B D E C F G 
+D B E A F C G 
+D E B F G C A 
+'''
diff --git a/21/2.cpp b/21/2.cpp
new file mode 100644
index 0000000..b723d60
--- /dev/null
+++ b/21/2.cpp
@@ -0,0 +1,29 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+void heapSort(vector<int>& arr) {
+    priority_queue<int> h;
+    // 모든 원소를 차례대로 힙에 삽입
+    for (int i = 0; i < arr.size(); i++) {
+        h.push(-arr[i]);
+    }
+    // 힙에 삽입된 모든 원소를 차례대로 꺼내어 출력
+    while (!h.empty()) {
+        printf("%d\n", -h.top());
+        h.pop();
+    }
+}
+
+int n;
+vector<int> arr;
+
+int main() {
+    cin >> n;
+    for (int i = 0; i < n; i++) {
+        int x;
+        scanf("%d", &x);
+        arr.push_back(x);
+    }
+    heapSort(arr);
+}
diff --git a/21/2.py b/21/2.py
new file mode 100644
index 0000000..7e95dad
--- /dev/null
+++ b/21/2.py
@@ -0,0 +1,25 @@
+import sys
+import heapq
+input = sys.stdin.readline
+
+def heapsort(iterable):
+    h = []
+    result = []
+    # 모든 원소를 차례대로 힙에 삽입
+    for value in iterable:
+        heapq.heappush(h, value)
+    # 힙에 삽입된 모든 원소를 차례대로 꺼내어 담기
+    for i in range(len(h)):
+        result.append(heapq.heappop(h))
+    return result
+
+n = int(input())
+arr = []
+
+for i in range(n):
+    arr.append(int(input()))
+
+res = heapsort(arr)
+
+for i in range(n):
+    print(res[i])
diff --git a/21/3.cpp b/21/3.cpp
new file mode 100644
index 0000000..1e78791
--- /dev/null
+++ b/21/3.cpp
@@ -0,0 +1,62 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 전체 데이터의 개수는 최대 1,000,000개
+long long arr[1000001], tree[1000001];
+// 데이터의 개수(n), 변경 횟수(m), 구간 합 계산 횟수(k)
+int n, m, k;
+
+// i번째 수까지의 누적 합을 계산하는 함수
+long long prefixSum(int i) {
+    long long result = 0;
+    while(i > 0) {
+        result += tree[i];
+        // 0이 아닌 마지막 비트만큼 빼가면서 이동
+        i -= (i & -i);
+    }
+    return result;
+} 
+
+// i번째 수를 dif만큼 더하는 함수
+void update(int i, long long dif) {
+    while(i <= n) {
+        tree[i] += dif;
+        i += (i & -i);
+    }
+}
+
+// start부터 end까지의 구간 합을 계산하는 함수
+long long intervalSum(int start, int end) {
+    return prefixSum(end) - prefixSum(start - 1);
+}
+
+int main(void) {
+    scanf("%d %d %d", &n, &m, &k);
+    for(int i = 1; i <= n; i++) {
+        long long x;
+        scanf("%lld", &x);
+        arr[i] = x;
+        update(i, x);
+    }
+    int count = 0;
+    while(count++ < m + k) {
+        int op;
+        scanf("%d", &op);
+        // 업데이트(update) 연산인 경우
+        if(op == 1) {
+            int index;
+            long long value;
+            scanf("%d %lld", &index, &value);
+            update(index, value - arr[index]); // 바뀐 크기(dif)만큼 적용
+            arr[index] = value; // i번째 수를 value로 업데이트
+        }
+        // 구간 합(interval sum) 연산인 경우
+        else {
+            int start, end;
+            scanf("%d %d", &start, &end);
+            printf("%lld\n", intervalSum(start, end));
+        }
+    }
+    return 0;
+}
diff --git a/21/3.py b/21/3.py
new file mode 100644
index 0000000..333a733
--- /dev/null
+++ b/21/3.py
@@ -0,0 +1,43 @@
+import sys
+input = sys.stdin.readline
+
+# 데이터의 개수(n), 변경 횟수(m), 구간 합 계산 횟수(k)
+n, m, k = map(int, input().split())
+
+# 전체 데이터의 개수는 최대 1,000,000개
+arr = [0] * (n + 1)
+tree = [0] * (n + 1)
+
+# i번째 수까지의 누적 합을 계산하는 함수
+def prefix_sum(i):
+    result = 0
+    while i > 0:
+        result += tree[i]
+        # 0이 아닌 마지막 비트만큼 빼가면서 이동
+        i -= (i & -i)
+    return result
+
+# i번째 수를 dif만큼 더하는 함수
+def update(i, dif):
+    while i <= n:
+        tree[i] += dif
+        i += (i & -i)
+
+# start부터 end까지의 구간 합을 계산하는 함수
+def interval_sum(start, end):
+    return prefix_sum(end) - prefix_sum(start - 1)
+
+for i in range(1, n + 1):
+    x = int(input())
+    arr[i] = x
+    update(i, x)
+
+for i in range(m + k):
+    a, b, c = map(int, input().split())
+    # 업데이트(update) 연산인 경우
+    if a == 1:
+        update(b, c - arr[b]) # 바뀐 크기(dif)만큼 적용
+        arr[b] = c
+    # 구간 합(interval sum) 연산인 경우
+    else:
+        print(interval_sum(b, c))
diff --git a/21/4.cpp b/21/4.cpp
new file mode 100644
index 0000000..5976efa
--- /dev/null
+++ b/21/4.cpp
@@ -0,0 +1,67 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+// 노드의 개수(N), 간선의 개수(M)
+// 노드의 개수는 최대 500개라고 가정
+int n, m;
+// 모든 간선에 대한 정보를 담는 리스트 만들기
+vector<pair<int, pair<int, int> > > edges;
+// 최단 거리 테이블 만들기
+long long d[501]; // 오버 플로우 및 언더 플로우 방지
+
+bool bf(int start) {
+    // 시작 노드에 대해서 초기화
+    d[start] = 0;
+    // 전체 n - 1번의 라운드(round)를 반복
+    for (int i = 0; i < n; i++) {
+        // 매 반복마다 "모든 간선"을 확인하며
+        for (int j = 0; j < m; j++) {
+            int cur_node = edges[j].first;
+            int next_node = edges[j].second.first;
+            int edge_cost = edges[j].second.second;
+            // 현재 간선을 거쳐서 다른 노드로 이동하는 거리가 더 짧은 경우
+            if (d[cur_node] != INF and d[next_node] > d[cur_node] + edge_cost) {
+                d[next_node] = d[cur_node] + edge_cost;
+                // n번째 라운드에서도 값이 갱신된다면 음수 순환이 존재
+                if (i == n - 1) return true;
+            }
+        }
+    }
+    return false;
+}
+
+int main(void) {
+    cin >> n >> m;
+
+    // 모든 간선 정보를 입력받기
+    for (int i = 0; i < m; i++) {
+        int a, b, c;
+        cin >> a >> b >> c;
+        // a번 노드에서 b번 노드로 가는 비용이 c라는 의미
+        edges.push_back({a, {b, c}});
+    }
+
+    // 최단 거리 테이블을 모두 무한으로 초기화
+    fill_n(d, 501, INF);
+    
+    // 벨만 포드 알고리즘을 수행
+    bool negative_cycle = bf(1); // 1번 노드가 시작 노드
+
+    if (negative_cycle) {
+        cout << "-1" << '\n';
+        return 0;
+    }
+    // 1번 노드를 제외한 다른 모든 노드로 가기 위한 최단 거리를 출력
+    for (int i = 2; i <= n; i++) {
+        // 도달할 수 없는 경우, -1을 출력
+        if (d[i] == INF) {
+            cout << "-1" << '\n';
+        }
+        // 도달할 수 있는 경우 거리를 출력
+        else {
+            cout << d[i] << '\n';
+        }
+    }
+}
diff --git a/21/4.py b/21/4.py
new file mode 100644
index 0000000..fcbcf02
--- /dev/null
+++ b/21/4.py
@@ -0,0 +1,49 @@
+import sys
+input = sys.stdin.readline
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
+
+# 노드의 개수, 간선의 개수를 입력받기
+n, m = map(int, input().split())
+# 모든 간선에 대한 정보를 담는 리스트 만들기
+edges = []
+# 최단 거리 테이블을 모두 무한으로 초기화
+distance = [INF] * (n + 1)
+
+# 모든 간선 정보를 입력받기
+for _ in range(m):
+    a, b, c = map(int, input().split())
+    # a번 노드에서 b번 노드로 가는 비용이 c라는 의미
+    edges.append((a, b, c))
+
+def bf(start):
+    # 시작 노드에 대해서 초기화
+    distance[start] = 0
+    # 전체 n - 1번의 라운드(round)를 반복
+    for i in range(n):
+        # 매 반복마다 "모든 간선"을 확인하며
+        for j in range(m):
+            cur_node = edges[j][0]
+            next_node = edges[j][1]
+            edge_cost = edges[j][2]
+            # 현재 간선을 거쳐서 다른 노드로 이동하는 거리가 더 짧은 경우
+            if distance[cur_node] != INF and distance[next_node] > distance[cur_node] + edge_cost:
+                distance[next_node] = distance[cur_node] + edge_cost
+                # n번째 라운드에서도 값이 갱신된다면 음수 순환이 존재
+                if i == n - 1:
+                    return True
+    return False
+
+# 벨만 포드 알고리즘을 수행
+negative_cycle = bf(1) # 1번 노드가 시작 노드
+
+if negative_cycle:
+    print("-1")
+else:
+    # 1번 노드를 제외한 다른 모든 노드로 가기 위한 최단 거리를 출력
+    for i in range(2, n + 1):
+        # 도달할 수 없는 경우, -1을 출력
+        if distance[i] == INF:
+            print("-1")
+        # 도달할 수 있는 경우 거리를 출력
+        else:
+            print(distance[i])
diff --git a/21/5.cpp b/21/5.cpp
new file mode 100644
index 0000000..a1ab904
--- /dev/null
+++ b/21/5.cpp
@@ -0,0 +1,57 @@
+#include <bits/stdc++.h>
+#define MAX 100001
+
+using namespace std;
+
+int n, m;
+int parent[MAX]; // 부모에 대한 정보
+int d[MAX]; // 각 노드까지의 깊이(depth)
+int c[MAX]; // 각 노드의 깊이가 계산되었는지 여부
+vector<int> graph[MAX]; // 그래프(graph) 정보
+
+// 루트 노드부터 시작하여 깊이(depth)를 구하는 함수
+void dfs(int x, int depth) {
+    c[x] = true;
+    d[x] = depth;
+    for (int i = 0; i < graph[x].size(); i++) {
+        int y = graph[x][i];
+        if (c[y]) continue; // 이미 깊이를 구했다면 넘기기
+        parent[y] = x;
+        dfs(y, depth + 1);
+    }
+}
+
+// A와 B의 최소 공통 조상을 찾는 함수
+int lca(int a, int b) {
+    // 먼저 깊이(depth)가 동일하도록
+    while (d[a] != d[b]) {
+        if (d[a] > d[b]) {
+            a = parent[a];
+        }
+        else b = parent[b];
+    }
+    // 노드가 같아지도록
+    while (a != b) {
+        a = parent[a];
+        b = parent[b];
+    }
+    return a;
+}
+
+int main() {
+    cin >> n;
+    for (int i = 0; i < n - 1; i++) {
+        int a, b;
+        cin >> a >> b;
+        graph[a].push_back(b);
+        graph[b].push_back(a);
+    }
+    dfs(1, 0); // 루트 노드는 1번 노드
+
+    cin >> m;
+    for (int i = 0; i < m; i++) {
+        int a, b;
+        cin >> a >> b;
+        cout << lca(a, b) << '\n';
+    }
+}
diff --git a/21/5.py b/21/5.py
new file mode 100644
index 0000000..28fc400
--- /dev/null
+++ b/21/5.py
@@ -0,0 +1,46 @@
+import sys
+sys.setrecursionlimit(int(1e5)) # 런타임 오류를 피하기 위한 재귀 깊이 제한 설정
+
+n = int(input())
+
+parent = [0] * (n + 1) # 부모 노드 정보
+d = [0] * (n + 1) # 각 노드까지의 깊이
+c = [0] * (n + 1) # 각 노드의 깊이가 계산되었는지 여부
+graph = [[] for _ in range(n + 1)] # 그래프(graph) 정보
+
+for _ in range(n - 1):
+    a, b = map(int, input().split())
+    graph[a].append(b)
+    graph[b].append(a)
+
+# 루트 노드부터 시작하여 깊이(depth)를 구하는 함수
+def dfs(x, depth):
+    c[x] = True
+    d[x] = depth
+    for y in graph[x]:
+        if c[y]: # 이미 깊이를 구했다면 넘기기
+            continue
+        parent[y] = x
+        dfs(y, depth + 1)
+
+# A와 B의 최소 공통 조상을 찾는 함수
+def lca(a, b):
+    # 먼저 깊이(depth)가 동일하도록
+    while d[a] != d[b]:
+        if d[a] > d[b]:
+            a = parent[a]
+        else:
+            b = parent[b]
+    # 노드가 같아지도록
+    while a != b:
+        a = parent[a]
+        b = parent[b]
+    return a
+
+dfs(1, 0) # 루트 노드는 1번 노드
+
+m = int(input())
+
+for i in range(m):
+    a, b = map(int, input().split())
+    print(lca(a, b))
diff --git a/21/6.cpp b/21/6.cpp
new file mode 100644
index 0000000..3a9bf4e
--- /dev/null
+++ b/21/6.cpp
@@ -0,0 +1,76 @@
+#include <bits/stdc++.h>
+#define MAX 100001
+#define LOG 21 // 2^20 = 1,000,000
+
+using namespace std;
+
+int n, m;
+int parent[MAX][LOG]; // 부모에 대한 정보
+int d[MAX]; // 각 노드까지의 깊이(depth)
+int c[MAX]; // 각 노드의 깊이가 계산되었는지 여부
+vector<int> graph[MAX]; // 그래프(graph) 정보
+
+// 루트 노드부터 시작하여 깊이(depth)를 구하는 함수
+void dfs(int x, int depth) {
+    c[x] = true;
+    d[x] = depth;
+    for (int i = 0; i < graph[x].size(); i++) {
+        int y = graph[x][i];
+        if (c[y]) continue; // 이미 깊이를 구했다면 넘기기
+        parent[y][0] = x;
+        dfs(y, depth + 1);
+    }
+}
+
+// 전체 부모 관계를 설정하는 함수
+void setParent() {
+    dfs(1, 0); // 루트 노드는 1번 노드
+    for (int i = 1; i < LOG; i++) {
+        for (int j = 1; j <= n; j++) {
+            parent[j][i] = parent[parent[j][i - 1]][i - 1];
+        }
+    }
+}
+
+// A와 B의 최소 공통 조상을 찾는 함수
+int lca(int a, int b) {
+    // y가 더 깊도록 설정
+    if(d[a] > d[b]) {
+        swap(a, b);
+    }
+    // 먼저 깊이(depth)가 동일하도록
+    for(int i = LOG - 1; i >= 0; i--) {
+        if(d[b] - d[a] >= (1 << i)) {
+            b = parent[b][i];
+        }
+    }
+    // 부모가 같아지도록 
+    if(a == b) return a;
+    for(int i = LOG - 1; i >= 0; i--) {
+        // 조상을 향해 거슬러 올라가기
+        if(parent[a][i] != parent[b][i]) {
+            a = parent[a][i];
+            b = parent[b][i];
+        }
+    }
+    // 이후에 부모가 찾고자 하는 조상
+    return parent[a][0];
+}
+
+int main() {
+    scanf("%d", &n);
+    for (int i = 0; i < n - 1; i++) {
+        int a, b;
+        scanf("%d %d", &a, &b);
+        graph[a].push_back(b);
+        graph[b].push_back(a);
+    }
+    setParent();
+
+    cin >> m;
+    for (int i = 0; i < m; i++) {
+        int a, b;
+        scanf("%d %d", &a, &b);
+        printf("%d\n", lca(a, b));
+    }
+}
diff --git a/21/6.py b/21/6.py
new file mode 100644
index 0000000..2c80e57
--- /dev/null
+++ b/21/6.py
@@ -0,0 +1,60 @@
+import sys
+input = sys.stdin.readline # 시간 초과를 피하기 위한 빠른 입력 함수
+sys.setrecursionlimit(int(1e5)) # 런타임 오류를 피하기 위한 재귀 깊이 제한 설정
+LOG = 21 # 2^20 = 1,000,000
+
+n = int(input())
+parent = [[0] * LOG for _ in range(n + 1)] # 부모 노드 정보
+d = [0] * (n + 1) # 각 노드까지의 깊이
+c = [0] * (n + 1) # 각 노드의 깊이가 계산되었는지 여부
+graph = [[] for _ in range(n + 1)] # 그래프(graph) 정보
+
+for _ in range(n - 1):
+    a, b = map(int, input().split())
+    graph[a].append(b)
+    graph[b].append(a)
+
+# 루트 노드부터 시작하여 깊이(depth)를 구하는 함수
+def dfs(x, depth):
+    c[x] = True
+    d[x] = depth
+    for y in graph[x]:
+        if c[y]: # 이미 깊이를 구했다면 넘기기
+            continue
+        parent[y][0] = x
+        dfs(y, depth + 1)
+
+# 전체 부모 관계를 설정하는 함수
+def set_parent():
+    dfs(1, 0) # 루트 노드는 1번 노드
+    for i in range(1, LOG):
+        for j in range(1, n + 1):
+            parent[j][i] = parent[parent[j][i - 1]][i - 1]
+
+# A와 B의 최소 공통 조상을 찾는 함수
+def lca(a, b):
+    # b가 더 깊도록 설정
+    if d[a] > d[b]:
+        a, b = b, a
+    # 먼저 깊이(depth)가 동일하도록
+    for i in range(LOG - 1, -1, -1):
+        if d[b] - d[a] >= (1 << i):
+            b = parent[b][i]
+    # 부모가 같아지도록
+    if a == b:
+        return a;
+    for i in range(LOG - 1, -1, -1):
+        # 조상을 향해 거슬러 올라가기
+        if parent[a][i] != parent[b][i]:
+            a = parent[a][i]
+            b = parent[b][i]
+    # 이후에 부모가 찾고자 하는 조상
+    return parent[a][0]
+
+set_parent()
+
+m = int(input())
+
+for i in range(m):
+    a, b = map(int, input().split())
+    print(lca(a, b))
diff --git a/3/1.cpp b/3/1.cpp
new file mode 100644
index 0000000..df49e40
--- /dev/null
+++ b/3/1.cpp
@@ -0,0 +1,16 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n = 1260;
+int cnt = 0;
+int coinTypes[4] = {500, 100, 50, 10};
+
+int main() {
+    for (int i = 0; i < 4; i++) {
+        int coin = coinTypes[i];
+        cnt += n / coin;
+        n %= coin;
+    }
+    cout << cnt << '\n';
+}
diff --git a/3/1.java b/3/1.java
new file mode 100644
index 0000000..ca0a3b3
--- /dev/null
+++ b/3/1.java
@@ -0,0 +1,17 @@
+public class Main {
+
+    public static void main(String[] args) {
+        int n = 1260;
+        int cnt = 0;
+        int[] coinTypes = {500, 100, 50, 10};
+		
+        for (int i = 0; i < 4; i++) {
+            int coin = coinTypes[i];
+            cnt += n / coin;
+            n %= coin;
+        }
+
+        System.out.println(cnt);
+    }
+
+}
diff --git a/3/1.py b/3/1.py
index 9bb2cc7..b92bc17 100644
--- a/3/1.py
+++ b/3/1.py
@@ -2,9 +2,9 @@
 count = 0
 
 # 큰 단위의 화폐부터 차례대로 확인하기
-list = [500, 100, 50, 10]
+coin_types = [500, 100, 50, 10]
 
-for coin in list:
+for coin in coin_types:
     count += n // coin # 해당 화폐로 거슬러 줄 수 있는 동전의 개수 세기
     n %= coin
 
diff --git a/3/2.cpp b/3/2.cpp
new file mode 100644
index 0000000..5ede689
--- /dev/null
+++ b/3/2.cpp
@@ -0,0 +1,32 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, m, k;
+vector<int> v;
+
+int main() {
+    // N, M, K를 공백을 기준으로 구분하여 입력 받기
+    cin >> n >> m >> k;
+
+    // N개의 수를 공백을 기준으로 구분하여 입력 받기
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        v.push_back(x);
+    }
+
+    sort(v.begin(), v.end()); // 입력 받은 수들 정렬하기
+    int first = v[n - 1]; // 가장 큰 수
+    int second = v[n - 2]; // 두 번째로 큰 수
+
+    // 가장 큰 수가 더해지는 횟수 계산
+    int cnt = (m / (k + 1)) * k;
+    cnt += m % (k + 1);
+
+    int result = 0;
+    result += cnt * first; // 가장 큰 수 더하기
+    result += (m - cnt) * second; // 두 번째로 큰 수 더하기
+
+    cout << result << '\n'; // 최종 답안 출력
+}
\ No newline at end of file
diff --git a/3/2.java b/3/2.java
new file mode 100644
index 0000000..9ae7b31
--- /dev/null
+++ b/3/2.java
@@ -0,0 +1,34 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N, M, K를 공백을 기준으로 구분하여 입력 받기
+        int n = sc.nextInt();
+        int m = sc.nextInt();
+        int k = sc.nextInt();
+
+        // N개의 수를 공백을 기준으로 구분하여 입력 받기
+        int[] arr = new int[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+
+        Arrays.sort(arr); // 입력 받은 수들 정렬하기
+        int first = arr[n - 1]; // 가장 큰 수
+        int second = arr[n - 2]; // 두 번째로 큰 수
+
+        // 가장 큰 수가 더해지는 횟수 계산
+        int cnt = (m / (k + 1)) * k;
+        cnt += m % (k + 1);
+
+        int result = 0;
+        result += cnt * first; // 가장 큰 수 더하기
+        result += (m - cnt) * second; // 두 번째로 큰 수 더하기
+
+        System.out.println(result);
+    }
+
+}
\ No newline at end of file
diff --git a/3/4.cpp b/3/4.cpp
new file mode 100644
index 0000000..bbe1fcc
--- /dev/null
+++ b/3/4.cpp
@@ -0,0 +1,26 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, m;
+int result;
+
+int main() {
+    // N, M을 공백을 기준으로 구분하여 입력 받기
+    cin >> n >> m;
+
+    // 한 줄씩 입력 받아 확인하기
+    for (int i = 0; i < n; i++) {
+        // 현재 줄에서 '가장 작은 수' 찾기
+        int min_value = 10001;
+        for (int j = 0; j < m; j++) {
+            int x;
+            cin >> x;
+            min_value = min(min_value, x);
+        }
+        // '가장 작은 수'들 중에서 가장 큰 수 찾기
+        result = max(result, min_value);
+    }
+
+    cout << result << '\n'; // 최종 답안 출력
+}
\ No newline at end of file
diff --git a/3/4.java b/3/4.java
new file mode 100644
index 0000000..9cedf9a
--- /dev/null
+++ b/3/4.java
@@ -0,0 +1,28 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N, M을 공백을 기준으로 구분하여 입력 받기
+        int n = sc.nextInt();
+        int m = sc.nextInt();
+        int result = 0;
+
+        // 한 줄씩 입력 받아 확인하기
+        for (int i = 0; i < n; i++) {
+            // 현재 줄에서 '가장 작은 수' 찾기
+            int min_value = 10001;
+            for (int j = 0; j < m; j++) {
+                int x = sc.nextInt();
+                min_value = Math.min(min_value, x);
+            }
+            // '가장 작은 수'들 중에서 가장 큰 수 찾기
+            result = Math.max(result, min_value);
+        }
+
+        System.out.println(result); // 최종 답안 출력
+    }
+
+}
\ No newline at end of file
diff --git a/3/4.py b/3/4.py
index 93e564d..0e3ef9c 100644
--- a/3/4.py
+++ b/3/4.py
@@ -1,20 +1,15 @@
-# N, K을 공백을 기준으로 구분하여 입력 받기
-n, k = map(int, input().split())
+# N, M을 공백을 기준으로 구분하여 입력 받기
+n, m = map(int, input().split())
 
 result = 0
+# 한 줄씩 입력 받아 확인하기
+for i in range(n):
+    data = list(map(int, input().split()))
+    # 현재 줄에서 '가장 작은 수' 찾기
+    min_value = 10001
+    for a in data:
+        min_value = min(min_value, a)
+    # '가장 작은 수'들 중에서 가장 큰 수 찾기
+    result = max(result, min_value)
 
-while True:
-    # N이 K로 나누어 떨어지는 수가 될 때까지만 1씩 빼기
-    target = (n // k) * k
-    result += (n - target)
-    n = target
-    # N이 K보다 작을 때 (더 이상 나눌 수 없을 때) 반복문 탈출
-    if n < k:
-        break
-    # K로 나누기
-    result += 1
-    n //= k
-
-# 마지막으로 남은 수에 대하여 1씩 빼기
-result += (n - 1)
-print(result)
+print(result) # 최종 답안 출력
\ No newline at end of file
diff --git a/3/5.py b/3/5.py
new file mode 100644
index 0000000..46d0e93
--- /dev/null
+++ b/3/5.py
@@ -0,0 +1,20 @@
+# N, K을 공백을 기준으로 구분하여 입력 받기
+n, k = map(int, input().split())
+result = 0
+
+// N이 K 이상이라면 K로 계속 나누기
+while n >= k:
+    # N이 K로 나누어 떨어지지 않는다면 N에서 1씩 빼기
+    while n % k != 0:
+        n -= 1
+        result += 1
+    # K로 나누기
+    n //= k
+    result += 1
+
+# 마지막으로 남은 수에 대하여 1씩 빼기
+while n > 1:
+    n -= 1
+    result += 1
+
+print(result)
\ No newline at end of file
diff --git a/3/6.cpp b/3/6.cpp
new file mode 100644
index 0000000..069b1b7
--- /dev/null
+++ b/3/6.cpp
@@ -0,0 +1,27 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, k;
+int result;
+
+int main() {
+    // N, K를 공백을 기준으로 구분하여 입력 받기
+    cin >> n >> k;
+
+    while (true) {
+        // N이 K로 나누어 떨어지는 수가 될 때까지만 1씩 빼기
+        int target = (n / k) * k;
+        result += (n - target);
+        n = target;
+        // N이 K보다 작을 때 (더 이상 나눌 수 없을 때) 반복문 탈출
+        if (n < k) break;
+        // K로 나누기
+        result += 1;
+        n /= k;
+    }
+
+    // 마지막으로 남은 수에 대하여 1씩 빼기
+    result += (n - 1);
+    cout << result << '\n';
+}
\ No newline at end of file
diff --git a/3/6.java b/3/6.java
new file mode 100644
index 0000000..f3bd9fb
--- /dev/null
+++ b/3/6.java
@@ -0,0 +1,30 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N, K를 공백을 기준으로 구분하여 입력 받기
+        int n = sc.nextInt();
+        int k = sc.nextInt();
+        int result = 0;
+
+        while (true) {
+            // N이 K로 나누어 떨어지는 수가 될 때까지만 1씩 빼기
+            int target = (n / k) * k;
+            result += (n - target);
+            n = target;
+            // N이 K보다 작을 때 (더 이상 나눌 수 없을 때) 반복문 탈출
+            if (n < k) break;
+            // K로 나누기
+            result += 1;
+            n /= k;
+        }
+
+        // 마지막으로 남은 수에 대하여 1씩 빼기
+        result += (n - 1);
+        System.out.println(result);
+    }
+
+}
\ No newline at end of file
diff --git a/3/6.py b/3/6.py
new file mode 100644
index 0000000..3323902
--- /dev/null
+++ b/3/6.py
@@ -0,0 +1,20 @@
+# N, K공백을 기준으로 구분하여 입력 받기
+n, k = map(int, input().split())
+
+result = 0
+
+while True:
+    # N이 K로 나누어 떨어지는 수가 될 때까지만 1씩 빼기
+    target = (n // k) * k
+    result += (n - target)
+    n = target
+    # N이 K보다 작을 때 (더 이상 나눌 수 없을 때) 반복문 탈출
+    if n < k:
+        break
+    # K로 나누기
+    result += 1
+    n //= k
+
+# 마지막으로 남은 수에 대하여 1씩 빼기
+result += (n - 1)
+print(result)
diff --git a/4/1.cpp b/4/1.cpp
new file mode 100644
index 0000000..2fd4355
--- /dev/null
+++ b/4/1.cpp
@@ -0,0 +1,38 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// N을 입력받기
+int n;
+string plans;
+int x = 1, y = 1;
+
+// L, R, U, D에 따른 이동 방향 
+int dx[4] = {0, 0, -1, 1};
+int dy[4] = {-1, 1, 0, 0};
+char moveTypes[4] = {'L', 'R', 'U', 'D'};
+
+int main(void) {
+    cin >> n;
+    cin.ignore(); // 버퍼 비우기 
+    getline(cin, plans);
+    // 이동 계획을 하나씩 확인
+    for (int i = 0; i < plans.size(); i++) {
+        char plan = plans[i];
+        // 이동 후 좌표 구하기 
+        int nx = -1, ny = -1;
+        for (int j = 0; j < 4; j++) {
+            if (plan == moveTypes[j]) {
+                nx = x + dx[j];
+                ny = y + dy[j];
+            }
+        }
+        // 공간을 벗어나는 경우 무시 
+        if (nx < 1 || ny < 1 || nx > n || ny > n) continue;
+        // 이동 수행 
+        x = nx;
+        y = ny;
+    }
+    cout << x << ' ' << y << '\n';
+    return 0;
+}
diff --git a/4/1.java b/4/1.java
new file mode 100644
index 0000000..5344185
--- /dev/null
+++ b/4/1.java
@@ -0,0 +1,40 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N을 입력받기
+        int n = sc.nextInt();
+        sc.nextLine(); // 버퍼 비우기
+        String[] plans = sc.nextLine().split(" ");
+        int x = 1, y = 1;
+
+        // L, R, U, D에 따른 이동 방향 
+        int[] dx = {0, 0, -1, 1};
+        int[] dy = {-1, 1, 0, 0};
+        char[] moveTypes = {'L', 'R', 'U', 'D'};
+
+        // 이동 계획을 하나씩 확인
+        for (int i = 0; i < plans.length; i++) {
+            char plan = plans[i].charAt(0);
+            // 이동 후 좌표 구하기 
+            int nx = -1, ny = -1;
+            for (int j = 0; j < 4; j++) {
+                if (plan == moveTypes[j]) {
+                    nx = x + dx[j];
+                    ny = y + dy[j];
+                }
+            }
+            // 공간을 벗어나는 경우 무시 
+            if (nx < 1 || ny < 1 || nx > n || ny > n) continue;
+            // 이동 수행 
+            x = nx;
+            y = ny;
+        }
+
+        System.out.println(x + " " + y);
+    }
+
+}
\ No newline at end of file
diff --git a/4/1.py b/4/1.py
index 580859b..9c0cda6 100644
--- a/4/1.py
+++ b/4/1.py
@@ -1,4 +1,4 @@
-# N 입력 받기
+# N 입력받기
 n = int(input())
 x, y = 1, 1
 plans = input().split()
@@ -8,7 +8,7 @@
 dy = [-1, 1, 0, 0]
 move_types = ['L', 'R', 'U', 'D']
 
-# 이동 계획을 하나씩 확인하기
+# 이동 계획을 하나씩 확인
 for plan in plans:
     # 이동 후 좌표 구하기
     for i in range(len(move_types)):
diff --git a/4/2.cpp b/4/2.cpp
new file mode 100644
index 0000000..fd5e633
--- /dev/null
+++ b/4/2.cpp
@@ -0,0 +1,27 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int h, cnt;
+
+// 특정한 시각 안에 '3'이 포함되어 있는지의 여부
+bool check(int h, int m, int s) {
+    if (h % 10 == 3 || m / 10 == 3 || m % 10 == 3 || s / 10 == 3 || s % 10 == 3)
+        return true;
+    return false;
+}
+
+int main(void) {
+    // H를 입력받기 
+    cin >> h;
+    for (int i = 0; i <= h; i++) {
+        for (int j = 0; j < 60; j++) {
+            for (int k = 0; k < 60; k++) {
+                // 매 시각 안에 '3'이 포함되어 있다면 카운트 증가
+                if (check(i, j, k)) cnt++;
+            }
+        }
+    }
+    cout << cnt << '\n';
+    return 0;
+}
diff --git a/4/2.java b/4/2.java
new file mode 100644
index 0000000..fad0255
--- /dev/null
+++ b/4/2.java
@@ -0,0 +1,31 @@
+import java.util.*;
+
+public class Main {
+
+    // 특정한 시각 안에 '3'이 포함되어 있는지의 여부
+    public static boolean check(int h, int m, int s) {
+        if (h % 10 == 3 || m / 10 == 3 || m % 10 == 3 || s / 10 == 3 || s % 10 == 3)
+            return true;
+        return false;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // H를 입력받기 
+        int h = sc.nextInt();
+        int cnt = 0;
+
+        for (int i = 0; i <= h; i++) {
+            for (int j = 0; j < 60; j++) {
+                for (int k = 0; k < 60; k++) {
+                    // 매 시각 안에 '3'이 포함되어 있다면 카운트 증가
+                    if (check(i, j, k)) cnt++;
+                }
+            }
+        }
+
+        System.out.println(cnt);
+    }
+
+}
\ No newline at end of file
diff --git a/4/2.py b/4/2.py
index 8fa4ac2..c3f8be5 100644
--- a/4/2.py
+++ b/4/2.py
@@ -1,4 +1,4 @@
-# H 입력 받기
+# H를 입력받기
 h = int(input())
 
 count = 0
diff --git a/4/3.cpp b/4/3.cpp
new file mode 100644
index 0000000..467a125
--- /dev/null
+++ b/4/3.cpp
@@ -0,0 +1,31 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+string inputData;
+
+// 나이트가 이동할 수 있는 8가지 방향 정의
+int dx[] = {-2, -1, 1, 2, 2, 1, -1, -2};
+int dy[] = {-1, -2, -2, -1, 1, 2, 2, 1};
+
+int main(void) {
+    // 현재 나이트의 위치 입력받기
+    cin >> inputData;
+    int row = inputData[1] - '0';
+    int column = inputData[0] - 'a' + 1;
+
+    // 8가지 방향에 대하여 각 위치로 이동이 가능한지 확인
+    int result = 0;
+    for (int i = 0; i < 8; i++) {
+        // 이동하고자 하는 위치 확인
+        int nextRow = row + dx[i];
+        int nextColumn = column + dy[i];
+        // 해당 위치로 이동이 가능하다면 카운트 증가
+        if (nextRow >= 1 && nextRow <= 8 && nextColumn >= 1 && nextColumn <= 8) {
+            result += 1;
+        }
+    }
+
+    cout << result << '\n';
+    return 0;
+}
diff --git a/4/3.java b/4/3.java
new file mode 100644
index 0000000..e6d24c9
--- /dev/null
+++ b/4/3.java
@@ -0,0 +1,32 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // 현재 나이트의 위치 입력받기
+        String inputData = sc.nextLine();
+        int row = inputData.charAt(1) - '0';
+        int column = inputData.charAt(0) - 'a' + 1;
+
+        // 나이트가 이동할 수 있는 8가지 방향 정의
+        int[] dx = {-2, -1, 1, 2, 2, 1, -1, -2};
+        int[] dy = {-1, -2, -2, -1, 1, 2, 2, 1};
+
+        // 8가지 방향에 대하여 각 위치로 이동이 가능한지 확인
+        int result = 0;
+        for (int i = 0; i < 8; i++) {
+            // 이동하고자 하는 위치 확인
+            int nextRow = row + dx[i];
+            int nextColumn = column + dy[i];
+            // 해당 위치로 이동이 가능하다면 카운트 증가
+            if (nextRow >= 1 && nextRow <= 8 && nextColumn >= 1 && nextColumn <= 8) {
+                result += 1;
+            }
+        }
+
+        System.out.println(result);
+    }
+
+}
diff --git a/4/3.py b/4/3.py
index 9de0f9a..075404a 100644
--- a/4/3.py
+++ b/4/3.py
@@ -1,13 +1,10 @@
-# 현재 나이트의 위치 입력 받기
+# 현재 나이트의 위치 입력받기
 input_data = input()
 row = int(input_data[1])
 column = int(ord(input_data[0])) - int(ord('a')) + 1
 
 # 나이트가 이동할 수 있는 8가지 방향 정의
-steps = [
-    (-2, -1), (-1, -2), (1, -2), (2, -1),
-    (2, 1), (1, 2), (-1, 2), (-2, 1)
-]
+steps = [(-2, -1), (-1, -2), (1, -2), (2, -1), (2, 1), (1, 2), (-1, 2), (-2, 1)]
 
 # 8가지 방향에 대하여 각 위치로 이동이 가능한지 확인
 result = 0
diff --git a/4/4.cpp b/4/4.cpp
new file mode 100644
index 0000000..b6c58e3
--- /dev/null
+++ b/4/4.cpp
@@ -0,0 +1,72 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, m, x, y, direction;
+// 방문한 위치를 저장하기 위한 맵을 생성하여 0으로 초기화
+int d[50][50];
+// 전체 맵 정보
+int arr[50][50];
+
+// 북, 동, 남, 서 방향 정의
+int dx[] = {-1, 0, 1, 0};
+int dy[] = {0, 1, 0, -1};
+
+// 왼쪽으로 회전
+void turn_left() {
+    direction -= 1;
+    if (direction == -1) direction = 3;
+}
+
+int main(void) {
+    // N, M을 공백을 기준으로 구분하여 입력받기
+    cin >> n >> m;
+    // 현재 캐릭터의 X 좌표, Y 좌표, 방향을 입력받기
+    cin >> x >> y >> direction;
+    d[x][y] = 1; // 현재 좌표 방문 처리
+
+    // 전체 맵 정보를 입력 받기
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < m; j++) {
+            int x;
+            cin >> x;
+            arr[i][j] = x;
+        }
+    }
+
+    // 시뮬레이션 시작
+    int cnt = 1;
+    int turn_time = 0;
+    while (true) {
+        // 왼쪽으로 회전
+        turn_left();
+        int nx = x + dx[direction];
+        int ny = y + dy[direction];
+        // 회전한 이후 정면에 가보지 않은 칸이 존재하는 경우 이동
+        if (d[nx][ny] == 0 && arr[nx][ny] == 0) {
+            d[nx][ny] = 1;
+            x = nx;
+            y = ny;
+            cnt += 1;
+            turn_time = 0;
+            continue;
+        }
+        // 회전한 이후 정면에 가보지 않은 칸이 없거나 바다인 경우
+        else turn_time += 1;
+        // 네 방향 모두 갈 수 없는 경우
+        if (turn_time == 4) {
+            nx = x - dx[direction];
+            ny = y - dy[direction];
+            // 뒤로 갈 수 있다면 이동하기
+            if (arr[nx][ny] == 0) {
+                x = nx;
+                y = ny;
+            }
+            // 뒤가 바다로 막혀있는 경우
+            else break;
+            turn_time = 0;
+        }
+    }
+
+    cout << cnt << '\n';
+}
diff --git a/4/4.java b/4/4.java
new file mode 100644
index 0000000..639d442
--- /dev/null
+++ b/4/4.java
@@ -0,0 +1,78 @@
+import java.util.*;
+
+public class Main {
+
+    public static int n, m, x, y, direction;
+    // 방문한 위치를 저장하기 위한 맵을 생성하여 0으로 초기화
+    public static int[][] d = new int[50][50];
+    // 전체 맵 정보
+    public static int[][] arr = new int [50][50];
+
+    // 북, 동, 남, 서 방향 정의
+    public static int dx[] = {-1, 0, 1, 0};
+    public static int dy[] = {0, 1, 0, -1};
+
+    // 왼쪽으로 회전
+    public static void turn_left() {
+        direction -= 1;
+        if (direction == -1) direction = 3;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N, M을 공백을 기준으로 구분하여 입력받기
+        n = sc.nextInt();
+        m = sc.nextInt();
+        
+        // 현재 캐릭터의 X 좌표, Y 좌표, 방향을 입력받기
+        x = sc.nextInt();
+        y = sc.nextInt();
+        direction = sc.nextInt();
+        d[x][y] = 1; // 현재 좌표 방문 처리
+
+        // 전체 맵 정보를 입력 받기
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                arr[i][j] = sc.nextInt();
+            }
+        }
+
+        // 시뮬레이션 시작
+        int cnt = 1;
+        int turn_time = 0;
+        while (true) {
+            // 왼쪽으로 회전
+            turn_left();
+            int nx = x + dx[direction];
+            int ny = y + dy[direction];
+            // 회전한 이후 정면에 가보지 않은 칸이 존재하는 경우 이동
+            if (d[nx][ny] == 0 && arr[nx][ny] == 0) {
+                d[nx][ny] = 1;
+                x = nx;
+                y = ny;
+                cnt += 1;
+                turn_time = 0;
+                continue;
+            }
+            // 회전한 이후 정면에 가보지 않은 칸이 없거나 바다인 경우
+            else turn_time += 1;
+            // 네 방향 모두 갈 수 없는 경우
+            if (turn_time == 4) {
+                nx = x - dx[direction];
+                ny = y - dy[direction];
+                // 뒤로 갈 수 있다면 이동하기
+                if (arr[nx][ny] == 0) {
+                    x = nx;
+                    y = ny;
+                }
+                // 뒤가 바다로 막혀있는 경우
+                else break;
+                turn_time = 0;
+            }
+        }
+
+        System.out.println(cnt);
+    }
+
+}
\ No newline at end of file
diff --git a/4/4.py b/4/4.py
index 59ff45b..f82b4a2 100644
--- a/4/4.py
+++ b/4/4.py
@@ -1,13 +1,13 @@
-# N, M을 공백을 기준으로 구분하여 입력 받기
+# N, M을 공백을 기준으로 구분하여 입력받기
 n, m = map(int, input().split())
 
-# 방문한 위치를 저장하기 위한 맵을 생성하여 0으로 초기화합니다.
+# 방문한 위치를 저장하기 위한 맵을 생성하여 0으로 초기화
 d = [[0] * m for _ in range(n)]
-# 현재 캐릭터의 X 좌표, Y 좌표, 방향을 입력 받기
+# 현재 캐릭터의 X 좌표, Y 좌표, 방향을 입력받기
 x, y, direction = map(int, input().split())
 d[x][y] = 1 # 현재 좌표 방문 처리
 
-# 전체 맵 정보를 입력 받습니다.
+# 전체 맵 정보를 입력받기
 array = []
 for i in range(n):
     array.append(list(map(int, input().split())))
@@ -46,7 +46,7 @@ def turn_left():
     if turn_time == 4:
         nx = x - dx[direction]
         ny = y - dy[direction]
-        # 뒤로 갈 수 있다면 이동합니다.
+        # 뒤로 갈 수 있다면 이동하기
         if array[nx][ny] == 0:
             x = nx
             y = ny
@@ -55,5 +55,5 @@ def turn_left():
             break
         turn_time = 0
 
-# 정답을 출력합니다.
+# 정답 출력
 print(count)
diff --git a/5/1.cpp b/5/1.cpp
new file mode 100644
index 0000000..3f7b7c0
--- /dev/null
+++ b/5/1.cpp
@@ -0,0 +1,22 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+stack<int> s;
+
+int main(void) {
+    // 삽입(5) - 삽입(2) - 삽입(3) - 삽입(7) - 삭제() - 삽입(1) - 삽입(4) - 삭제()
+    s.push(5);
+    s.push(2);
+    s.push(3);
+    s.push(7);
+    s.pop();
+    s.push(1);
+    s.push(4);
+    s.pop();
+    // 스택의 최상단 원소부터 출력
+    while (!s.empty()) {
+        cout << s.top() << ' ';
+        s.pop();
+    }
+}
\ No newline at end of file
diff --git a/5/1.java b/5/1.java
new file mode 100644
index 0000000..96a3a4f
--- /dev/null
+++ b/5/1.java
@@ -0,0 +1,24 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Stack<Integer> s = new Stack<>();
+
+        // 삽입(5) - 삽입(2) - 삽입(3) - 삽입(7) - 삭제() - 삽입(1) - 삽입(4) - 삭제()
+        s.push(5);
+        s.push(2);
+        s.push(3);
+        s.push(7);
+        s.pop();
+        s.push(1);
+        s.push(4);
+        s.pop();
+        // 스택의 최상단 원소부터 출력
+        while (!s.empty()) {
+            System.out.println(s.peek());
+            s.pop();
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/5/1.py b/5/1.py
index 7c360cf..dfdc165 100644
--- a/5/1.py
+++ b/5/1.py
@@ -10,5 +10,5 @@
 stack.append(4)
 stack.pop()
 
-print(stack[::-1]) # 최상단 원소부터 출력
 print(stack) # 최하단 원소부터 출력
+print(stack[::-1]) # 최상단 원소부터 출력
diff --git a/5/10.cpp b/5/10.cpp
new file mode 100644
index 0000000..d89280e
--- /dev/null
+++ b/5/10.cpp
@@ -0,0 +1,48 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, m;
+int graph[1000][1000];
+
+// DFS로 특정 노드를 방문하고 연결된 모든 노드들도 방문
+bool dfs(int x, int y) {
+    // 주어진 범위를 벗어나는 경우에는 즉시 종료
+    if (x <= -1 || x >=n || y <= -1 || y >= m) {
+        return false;
+    }
+    // 현재 노드를 아직 방문하지 않았다면
+    if (graph[x][y] == 0) {
+        // 해당 노드 방문 처리
+        graph[x][y] = 1;
+        // 상, 하, 좌, 우의 위치들도 모두 재귀적으로 호출
+        dfs(x - 1, y);
+        dfs(x, y - 1);
+        dfs(x + 1, y);
+        dfs(x, y + 1);
+        return true;
+    }
+    return false;
+}
+
+int main() {
+    // N, M을 공백을 기준으로 구분하여 입력 받기
+    cin >> n >> m;
+    // 2차원 리스트의 맵 정보 입력 받기
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < m; j++) {
+            scanf("%1d", &graph[i][j]);
+        }
+    }
+    // 모든 노드(위치)에 대하여 음료수 채우기
+    int result = 0;
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < m; j++) {
+            // 현재 위치에서 DFS 수행
+            if (dfs(i, j)) {
+                result += 1;
+            }
+        }
+    }
+    cout << result << '\n'; // 정답 출력 
+}
\ No newline at end of file
diff --git a/5/10.java b/5/10.java
new file mode 100644
index 0000000..182fa72
--- /dev/null
+++ b/5/10.java
@@ -0,0 +1,57 @@
+import java.util.*;
+
+public class Main {
+
+    public static int n, m;
+    public static int[][] graph = new int[1000][1000];
+
+    // DFS로 특정 노드를 방문하고 연결된 모든 노드들도 방문
+    public static boolean dfs(int x, int y) {
+        // 주어진 범위를 벗어나는 경우에는 즉시 종료
+        if (x <= -1 || x >=n || y <= -1 || y >= m) {
+            return false;
+        }
+        // 현재 노드를 아직 방문하지 않았다면
+        if (graph[x][y] == 0) {
+            // 해당 노드 방문 처리
+            graph[x][y] = 1;
+            // 상, 하, 좌, 우의 위치들도 모두 재귀적으로 호출
+            dfs(x - 1, y);
+            dfs(x, y - 1);
+            dfs(x + 1, y);
+            dfs(x, y + 1);
+            return true;
+        }
+        return false;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N, M을 공백을 기준으로 구분하여 입력 받기
+        n = sc.nextInt();
+        m = sc.nextInt();
+        sc.nextLine(); // 버퍼 지우기
+
+        // 2차원 리스트의 맵 정보 입력 받기
+        for (int i = 0; i < n; i++) {
+            String str = sc.nextLine();
+            for (int j = 0; j < m; j++) {
+                graph[i][j] = str.charAt(j) - '0';
+            }
+        }
+
+        // 모든 노드(위치)에 대하여 음료수 채우기
+        int result = 0;
+        for (int i = 0; i < n; i++) {
+            for (int j = 0; j < m; j++) {
+                // 현재 위치에서 DFS 수행
+                if (dfs(i, j)) {
+                    result += 1;
+                }
+            }
+        }
+        System.out.println(result); // 정답 출력 
+    }
+
+}
\ No newline at end of file
diff --git a/5/11.cpp b/5/11.cpp
new file mode 100644
index 0000000..a6b7549
--- /dev/null
+++ b/5/11.cpp
@@ -0,0 +1,52 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, m;
+int graph[201][201];
+
+// 이동할 네 가지 방향 정의 (상, 하, 좌, 우) 
+int dx[] = {-1, 1, 0, 0};
+int dy[] = {0, 0, -1, 1};
+
+int bfs(int x, int y) {
+    // 큐(Queue) 구현을 위해 queue 라이브러리 사용 
+    queue<pair<int, int> > q;
+    q.push({x, y});
+    // 큐가 빌 때까지 반복하기 
+    while(!q.empty()) {
+        int x = q.front().first;
+        int y = q.front().second;
+        q.pop();
+        // 현재 위치에서 4가지 방향으로의 위치 확인
+        for (int i = 0; i < 4; i++) {
+            int nx = x + dx[i];
+            int ny = y + dy[i];
+            // 미로 찾기 공간을 벗어난 경우 무시
+            if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
+            // 벽인 경우 무시
+            if (graph[nx][ny] == 0) continue;
+            // 해당 노드를 처음 방문하는 경우에만 최단 거리 기록
+            if (graph[nx][ny] == 1) {
+                graph[nx][ny] = graph[x][y] + 1;
+                q.push({nx, ny});
+            } 
+        } 
+    }
+    // 가장 오른쪽 아래까지의 최단 거리 반환
+    return graph[n - 1][m - 1];
+}
+
+int main(void) {
+    // N, M을 공백을 기준으로 구분하여 입력 받기
+    cin >> n >> m;
+    // 2차원 리스트의 맵 정보 입력 받기
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < m; j++) {
+            scanf("%1d", &graph[i][j]);
+        }
+    }
+    // BFS를 수행한 결과 출력
+    cout << bfs(0, 0) << '\n';
+    return 0;
+}
\ No newline at end of file
diff --git a/5/11.java b/5/11.java
new file mode 100644
index 0000000..9350caf
--- /dev/null
+++ b/5/11.java
@@ -0,0 +1,79 @@
+import java.util.*;
+
+class Node {
+
+    private int x;
+    private int y;
+
+    public Node(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public int getX() {
+        return this.x;
+    }
+    
+    public int getY() {
+        return this.y;
+    }
+}
+
+public class Main {
+
+    public static int n, m;
+    public static int[][] graph = new int[201][201];
+
+    // 이동할 네 가지 방향 정의 (상, 하, 좌, 우) 
+    public static int dx[] = {-1, 1, 0, 0};
+    public static int dy[] = {0, 0, -1, 1};
+
+    public static int bfs(int x, int y) {
+        // 큐(Queue) 구현을 위해 queue 라이브러리 사용 
+        Queue<Node> q = new LinkedList<>();
+        q.offer(new Node(x, y));
+        // 큐가 빌 때까지 반복하기 
+        while(!q.isEmpty()) {
+            Node node = q.poll();
+            x = node.getX();
+            y = node.getY();
+            // 현재 위치에서 4가지 방향으로의 위치 확인
+            for (int i = 0; i < 4; i++) {
+                int nx = x + dx[i];
+                int ny = y + dy[i];
+                // 미로 찾기 공간을 벗어난 경우 무시
+                if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
+                // 벽인 경우 무시
+                if (graph[nx][ny] == 0) continue;
+                // 해당 노드를 처음 방문하는 경우에만 최단 거리 기록
+                if (graph[nx][ny] == 1) {
+                    graph[nx][ny] = graph[x][y] + 1;
+                    q.offer(new Node(nx, ny));
+                } 
+            } 
+        }
+        // 가장 오른쪽 아래까지의 최단 거리 반환
+        return graph[n - 1][m - 1];
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N, M을 공백을 기준으로 구분하여 입력 받기
+        n = sc.nextInt();
+        m = sc.nextInt();
+        sc.nextLine(); // 버퍼 지우기
+
+        // 2차원 리스트의 맵 정보 입력 받기
+        for (int i = 0; i < n; i++) {
+            String str = sc.nextLine();
+            for (int j = 0; j < m; j++) {
+                graph[i][j] = str.charAt(j) - '0';
+            }
+        }
+
+        // BFS를 수행한 결과 출력
+        System.out.println(bfs(0, 0));
+    }
+
+}
diff --git a/5/2.cpp b/5/2.cpp
new file mode 100644
index 0000000..9b35339
--- /dev/null
+++ b/5/2.cpp
@@ -0,0 +1,22 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+queue<int> q;
+
+int main(void) {
+    // 삽입(5) - 삽입(2) - 삽입(3) - 삽입(7) - 삭제() - 삽입(1) - 삽입(4) - 삭제()
+    q.push(5);
+    q.push(2);
+    q.push(3);
+    q.push(7);
+    q.pop();
+    q.push(1);
+    q.push(4);
+    q.pop();
+    // 먼저 들어온 원소부터 추출
+    while (!q.empty()) {
+        cout << q.front() << ' ';
+        q.pop();
+    }
+}
diff --git a/5/2.java b/5/2.java
new file mode 100644
index 0000000..4205197
--- /dev/null
+++ b/5/2.java
@@ -0,0 +1,23 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Queue<Integer> q = new LinkedList<>();
+
+        // 삽입(5) - 삽입(2) - 삽입(3) - 삽입(7) - 삭제() - 삽입(1) - 삽입(4) - 삭제()
+        q.offer(5);
+        q.offer(2);
+        q.offer(3);
+        q.offer(7);
+        q.poll();
+        q.offer(1);
+        q.offer(4);
+        q.poll();
+        // 먼저 들어온 원소부터 추출
+        while (!q.isEmpty()) {
+            System.out.println(q.poll());
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/5/2.py b/5/2.py
index 7374c62..c7e4b72 100644
--- a/5/2.py
+++ b/5/2.py
@@ -13,6 +13,6 @@
 queue.append(4)
 queue.popleft()
 
-print(queue) # 최하단 원소부터 출력
-queue.reverse() # 최상단 원소부터 출력하기 위해 역순으로 바꾸기
-print(queue) # 최상단 원소부터 출력
+print(queue) # 먼저 들어온 순서대로 출력
+queue.reverse() # 다음 출력을 위해 역순으로 바꾸기
+print(queue) # 나중에 들어온 원소부터 출력
diff --git a/5/3.cpp b/5/3.cpp
new file mode 100644
index 0000000..ab7540a
--- /dev/null
+++ b/5/3.cpp
@@ -0,0 +1,12 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+void recursiveFunction() {
+    cout << "재귀 함수를 호출합니다." << '\n';
+    recursiveFunction();
+}
+
+int main(void) {
+    recursiveFunction();
+}
\ No newline at end of file
diff --git a/5/3.java b/5/3.java
new file mode 100644
index 0000000..ecdc933
--- /dev/null
+++ b/5/3.java
@@ -0,0 +1,14 @@
+import java.util.*;
+
+public class Main {
+
+    public static void recursiveFunction() {
+        System.out.println("재귀 함수를 호출합니다.");
+        recursiveFunction();
+    }
+
+    public static void main(String[] args) {
+        recursiveFunction();
+    }
+
+}
\ No newline at end of file
diff --git a/5/4.cpp b/5/4.cpp
new file mode 100644
index 0000000..8c12a3e
--- /dev/null
+++ b/5/4.cpp
@@ -0,0 +1,15 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+void recursiveFunction(int i) {
+    // 100번째 호출을 했을 때 종료되도록 종료 조건 명시
+    if (i == 100) return;
+    cout << i << "번째 재귀 함수에서 " << i + 1 << "번째 재귀함수를 호출합니다." << '\n';
+    recursiveFunction(i + 1);
+    cout << i << "번째 재귀 함수를 종료합니다." << '\n';
+}
+
+int main(void) {
+    recursiveFunction(1);
+}
\ No newline at end of file
diff --git a/5/4.java b/5/4.java
new file mode 100644
index 0000000..ade3972
--- /dev/null
+++ b/5/4.java
@@ -0,0 +1,17 @@
+import java.util.*;
+
+public class Main {
+
+    public static void recursiveFunction(int i) {
+        // 100번째 호출을 했을 때 종료되도록 종료 조건 명시
+        if (i == 100) return;
+        System.out.println(i + "번째 재귀 함수에서 " + (i + 1) + "번째 재귀함수를 호출합니다.");
+        recursiveFunction(i + 1);
+        System.out.println(i + "번째 재귀 함수를 종료합니다.");
+    }
+
+    public static void main(String[] args) {
+        recursiveFunction(1);
+    }
+
+}
\ No newline at end of file
diff --git a/5/5.cpp b/5/5.cpp
new file mode 100644
index 0000000..c2e4859
--- /dev/null
+++ b/5/5.cpp
@@ -0,0 +1,27 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 반복적으로 구현한 n!
+int factorialIterative(int n) {
+    int result = 1;
+    // 1부터 n까지의 수를 차례대로 곱하기
+    for (int i = 1; i <= n; i++) {
+        result *= i;
+    }
+    return result;
+}
+
+// 재귀적으로 구현한 n!
+int factorialRecursive(int n) {
+    // n이 1 이하인 경우 1을 반환
+    if (n <= 1) return 1;
+    // n! = n * (n - 1)!를 그대로 코드로 작성하기
+    return n * factorialRecursive(n - 1);
+}
+
+int main(void) {
+    // 각각의 방식으로 구현한 n! 출력(n = 5)
+    cout << "반복적으로 구현:" << factorialIterative(5) << '\n';
+    cout << "재귀적으로 구현:" << factorialRecursive(5) << '\n';
+}
\ No newline at end of file
diff --git a/5/5.java b/5/5.java
new file mode 100644
index 0000000..6499d33
--- /dev/null
+++ b/5/5.java
@@ -0,0 +1,29 @@
+import java.util.*;
+
+public class Main {
+
+    // 반복적으로 구현한 n!
+    public static int factorialIterative(int n) {
+        int result = 1;
+        // 1부터 n까지의 수를 차례대로 곱하기
+        for (int i = 1; i <= n; i++) {
+            result *= i;
+        }
+        return result;
+    }
+
+    // 재귀적으로 구현한 n!
+    public static int factorialRecursive(int n) {
+        // n이 1 이하인 경우 1을 반환
+        if (n <= 1) return 1;
+        // n! = n * (n - 1)!를 그대로 코드로 작성하기
+        return n * factorialRecursive(n - 1);
+    }
+
+    public static void main(String[] args) {
+        // 각각의 방식으로 구현한 n! 출력(n = 5)
+        System.out.println("반복적으로 구현:" + factorialIterative(5));
+        System.out.println("재귀적으로 구현:" + factorialRecursive(5));
+    }
+
+}
\ No newline at end of file
diff --git a/5/5.py b/5/5.py
index 586e73e..d72386d 100644
--- a/5/5.py
+++ b/5/5.py
@@ -8,11 +8,11 @@ def factorial_iterative(n):
 
 # 재귀적으로 구현한 n!
 def factorial_recursive(n):        
-    if n == 1:
+    if n <= 1: # n이 1 이하인 경우 1을 반환
         return 1
     # n! = n * (n - 1)!를 그대로 코드로 작성하기
     return n * factorial_recursive(n - 1)
 
-# 각각의 방식으로 구현한 n! 출력 (n = 5)
+# 각각의 방식으로 구현한 n! 출력(n = 5)
 print('반복적으로 구현:', factorial_iterative(5))
 print('재귀적으로 구현:', factorial_recursive(5))
diff --git a/5/6.cpp b/5/6.cpp
new file mode 100644
index 0000000..4e1fa50
--- /dev/null
+++ b/5/6.cpp
@@ -0,0 +1,21 @@
+#include <bits/stdc++.h>
+#define INF 999999999 // 무한의 비용 선언
+
+using namespace std;
+
+// 2차원 리스트를 이용해 인접 행렬 표현
+int graph[3][3] = {
+    {0, 7, 5},
+    {7, 0, INF},
+    {5, INF, 0}
+};
+
+int main(void) {
+    // 그래프 출력
+    for (int i = 0; i < 3; i++) {
+        for (int j = 0; j < 3; j++) {
+            cout << graph[i][j] << ' ';
+        }
+        cout << '\n';
+    }
+}
\ No newline at end of file
diff --git a/5/6.java b/5/6.java
new file mode 100644
index 0000000..6f6084a
--- /dev/null
+++ b/5/6.java
@@ -0,0 +1,24 @@
+import java.util.*;
+
+public class Main {
+
+    public static final int INF = 999999999;
+    
+    // 2차원 리스트를 이용해 인접 행렬 표현
+    public static int[][] graph = {
+        {0, 7, 5},
+        {7, 0, INF},
+        {5, INF, 0}
+    };
+
+    public static void main(String[] args) {
+        // 그래프 출력
+        for (int i = 0; i < 3; i++) {
+            for (int j = 0; j < 3; j++) {
+                System.out.print(graph[i][j] + " ");
+            }
+            System.out.println();
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/5/6.py b/5/6.py
index 27e943c..aee4189 100644
--- a/5/6.py
+++ b/5/6.py
@@ -1,10 +1,10 @@
 INF = 999999999 # 무한의 비용 선언
 
 # 2차원 리스트를 이용해 인접 행렬 표현
-array = [
+graph = [
     [0, 7, 5],
     [7, 0, INF],
     [5, INF, 0]
 ]
 
-print(array)
+print(graph)
diff --git a/5/7.cpp b/5/7.cpp
new file mode 100644
index 0000000..66506d9
--- /dev/null
+++ b/5/7.cpp
@@ -0,0 +1,26 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 행(Row)이 3개인 인접 리스트 표현
+vector<pair<int, int> > graph[3];
+
+int main(void) {
+    // 노드 0에 연결된 노드 정보 저장 {노드, 거리}
+    graph[0].push_back({1, 7});
+    graph[0].push_back({2, 5});
+
+    // 노드 1에 연결된 노드 정보 저장 {노드, 거리}
+    graph[1].push_back({0, 7});
+
+    // 노드 2에 연결된 노드 정보 저장 {노드, 거리}
+    graph[2].push_back({0, 5});
+
+    // 그래프 출력
+    for (int i = 0; i < 3; i++) {
+        for (int j = 0; j < graph[i].size(); j++) {
+            cout << '(' << graph[i][j].first << ',' << graph[i][j].second << ')' << ' ';
+        }
+        cout << '\n';
+    } 
+}
\ No newline at end of file
diff --git a/5/7.java b/5/7.java
new file mode 100644
index 0000000..1d13451
--- /dev/null
+++ b/5/7.java
@@ -0,0 +1,48 @@
+import java.util.*;
+
+class Node {
+
+    private int index;
+    private int distance;
+
+    public Node(int index, int distance) {
+        this.index = index;
+        this.distance = distance;
+    }
+
+    public void show() {
+        System.out.print("(" + this.index + "," + this.distance + ") ");
+    }
+}
+
+public class Main {
+
+    // 행(Row)이 3개인 인접 리스트 표현
+    public static ArrayList<ArrayList<Node>> graph = new ArrayList<ArrayList<Node>>();
+
+    public static void main(String[] args) {
+        // 그래프 초기화
+        for (int i = 0; i < 3; i++) {
+            graph.add(new ArrayList<Node>());
+        }
+
+        // 노드 0에 연결된 노드 정보 저장 (노드, 거리)
+        graph.get(0).add(new Node(1, 7));
+        graph.get(0).add(new Node(2, 5));
+
+        // 노드 1에 연결된 노드 정보 저장 (노드, 거리)
+        graph.get(1).add(new Node(0, 7));
+
+        // 노드 2에 연결된 노드 정보 저장 (노드, 거리)
+        graph.get(2).add(new Node(0, 5));
+
+        // 그래프 출력
+        for (int i = 0; i < 3; i++) {
+            for (int j = 0; j < graph.get(i).size(); j++) {
+                graph.get(i).get(j).show();
+            }
+            System.out.println();
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/5/7.py b/5/7.py
index c79b5ba..4adde1f 100644
--- a/5/7.py
+++ b/5/7.py
@@ -1,14 +1,14 @@
 # 행(Row)이 3개인 2차원 리스트로 인접 리스트 표현
-array = [[] for _ in range(3)]
+graph = [[] for _ in range(3)]
+
+# 노드 0에 연결된 노드 정보 저장 (노드, 거리)
+graph[0].append((1, 7))
+graph[0].append((2, 5))
 
 # 노드 1에 연결된 노드 정보 저장 (노드, 거리)
-array[0].append((2, 7))
-array[0].append((3, 5))
+graph[1].append((0, 7))
 
 # 노드 2에 연결된 노드 정보 저장 (노드, 거리)
-array[1].append((1, 7))
-
-# 노드 3에 연결된 노드 정보 저장 (노드, 거리)
-array[2].append((1, 5))
+graph[2].append((0, 5))
 
-print(array)
+print(graph)
diff --git a/5/8.cpp b/5/8.cpp
new file mode 100644
index 0000000..e8759f7
--- /dev/null
+++ b/5/8.cpp
@@ -0,0 +1,56 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+bool visited[9];
+vector<int> graph[9];
+
+// DFS 함수 정의
+void dfs(int x) {
+    // 현재 노드를 방문 처리
+    visited[x] = true;
+    cout << x << ' ';
+    // 현재 노드와 연결된 다른 노드를 재귀적으로 방문
+    for (int i = 0; i < graph[x].size(); i++) {
+        int y = graph[x][i];
+        if (!visited[y]) dfs(y);
+    }
+}
+
+int main(void) {
+    // 노드 1에 연결된 노드 정보 저장 
+    graph[1].push_back(2);
+    graph[1].push_back(3);
+    graph[1].push_back(8);
+    
+    // 노드 2에 연결된 노드 정보 저장 
+    graph[2].push_back(1);
+    graph[2].push_back(7);
+    
+    // 노드 3에 연결된 노드 정보 저장 
+    graph[3].push_back(1);
+    graph[3].push_back(4);
+    graph[3].push_back(5);
+    
+    // 노드 4에 연결된 노드 정보 저장 
+    graph[4].push_back(3);
+    graph[4].push_back(5);
+    
+    // 노드 5에 연결된 노드 정보 저장 
+    graph[5].push_back(3);
+    graph[5].push_back(4);
+    
+    // 노드 6에 연결된 노드 정보 저장 
+    graph[6].push_back(7);
+    
+    // 노드 7에 연결된 노드 정보 저장 
+    graph[7].push_back(2);
+    graph[7].push_back(6);
+    graph[7].push_back(8);
+    
+    // 노드 8에 연결된 노드 정보 저장 
+    graph[8].push_back(1);
+    graph[8].push_back(7);
+    
+    dfs(1);
+}
\ No newline at end of file
diff --git a/5/8.java b/5/8.java
new file mode 100644
index 0000000..a85b769
--- /dev/null
+++ b/5/8.java
@@ -0,0 +1,63 @@
+import java.util.*;
+
+public class Main {
+
+    public static boolean[] visited = new boolean[9];
+    public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
+
+    // DFS 함수 정의
+    public static void dfs(int x) {
+        // 현재 노드를 방문 처리
+        visited[x] = true;
+        System.out.print(x + " ");
+        // 현재 노드와 연결된 다른 노드를 재귀적으로 방문
+        for (int i = 0; i < graph.get(x).size(); i++) {
+            int y = graph.get(x).get(i);
+            if (!visited[y]) dfs(y);
+        }
+    }
+
+    public static void main(String[] args) {
+        // 그래프 초기화
+        for (int i = 0; i < 9; i++) {
+            graph.add(new ArrayList<Integer>());
+        }
+
+        // 노드 1에 연결된 노드 정보 저장 
+        graph.get(1).add(2);
+        graph.get(1).add(3);
+        graph.get(1).add(8);
+        
+        // 노드 2에 연결된 노드 정보 저장 
+        graph.get(2).add(1);
+        graph.get(2).add(7);
+        
+        // 노드 3에 연결된 노드 정보 저장 
+        graph.get(3).add(1);
+        graph.get(3).add(4);
+        graph.get(3).add(5);
+        
+        // 노드 4에 연결된 노드 정보 저장 
+        graph.get(4).add(3);
+        graph.get(4).add(5);
+        
+        // 노드 5에 연결된 노드 정보 저장 
+        graph.get(5).add(3);
+        graph.get(5).add(4);
+        
+        // 노드 6에 연결된 노드 정보 저장 
+        graph.get(6).add(7);
+        
+        // 노드 7에 연결된 노드 정보 저장 
+        graph.get(7).add(2);
+        graph.get(7).add(6);
+        graph.get(7).add(8);
+        
+        // 노드 8에 연결된 노드 정보 저장 
+        graph.get(8).add(1);
+        graph.get(8).add(7);
+
+        dfs(1);
+    }
+
+}
\ No newline at end of file
diff --git a/5/8.py b/5/8.py
index 1c3585b..bcd734e 100644
--- a/5/8.py
+++ b/5/8.py
@@ -1,4 +1,4 @@
-# DFS 메서드 정의
+# DFS 함수 정의
 def dfs(graph, v, visited):
     # 현재 노드를 방문 처리
     visited[v] = True
@@ -8,7 +8,7 @@ def dfs(graph, v, visited):
         if not visited[i]:
             dfs(graph, i, visited)
 
-# 각 노드가 연결된 정보를 리스트 자료형으로 표현 (2차원 리스트)
+# 각 노드가 연결된 정보를 리스트 자료형으로 표현(2차원 리스트)
 graph = [
   [],
   [2, 3, 8],
@@ -21,7 +21,7 @@ def dfs(graph, v, visited):
   [1, 7]
 ]
 
-# 각 노드가 방문된 정보를 리스트 자료형으로 표현 (1차원 리스트)
+# 각 노드가 방문된 정보를 리스트 자료형으로 표현(1차원 리스트)
 visited = [False] * 9
 
 # 정의된 DFS 함수 호출
diff --git a/5/9.cpp b/5/9.cpp
new file mode 100644
index 0000000..fca7df9
--- /dev/null
+++ b/5/9.cpp
@@ -0,0 +1,67 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+bool visited[9];
+vector<int> graph[9];
+
+// BFS 함수 정의
+void bfs(int start) {
+    queue<int> q;
+    q.push(start);
+    // 현재 노드를 방문 처리
+    visited[start] = true;
+    // 큐가 빌 때까지 반복
+    while(!q.empty()) {
+    	// 큐에서 하나의 원소를 뽑아 출력
+        int x = q.front();
+        q.pop();
+        cout << x << ' ';
+        // 해당 원소와 연결된, 아직 방문하지 않은 원소들을 큐에 삽입
+        for(int i = 0; i < graph[x].size(); i++) {
+            int y = graph[x][i];
+            if(!visited[y]) {
+                q.push(y);
+                visited[y] = true;
+            }
+        }
+    }
+}
+
+int main(void) {
+    // 노드 1에 연결된 노드 정보 저장 
+    graph[1].push_back(2);
+    graph[1].push_back(3);
+    graph[1].push_back(8);
+    
+    // 노드 2에 연결된 노드 정보 저장 
+    graph[2].push_back(1);
+    graph[2].push_back(7);
+    
+    // 노드 3에 연결된 노드 정보 저장 
+    graph[3].push_back(1);
+    graph[3].push_back(4);
+    graph[3].push_back(5);
+    
+    // 노드 4에 연결된 노드 정보 저장 
+    graph[4].push_back(3);
+    graph[4].push_back(5);
+    
+    // 노드 5에 연결된 노드 정보 저장 
+    graph[5].push_back(3);
+    graph[5].push_back(4);
+    
+    // 노드 6에 연결된 노드 정보 저장 
+    graph[6].push_back(7);
+    
+    // 노드 7에 연결된 노드 정보 저장 
+    graph[7].push_back(2);
+    graph[7].push_back(6);
+    graph[7].push_back(8);
+    
+    // 노드 8에 연결된 노드 정보 저장 
+    graph[8].push_back(1);
+    graph[8].push_back(7);
+    
+    bfs(1);
+}
\ No newline at end of file
diff --git a/5/9.java b/5/9.java
new file mode 100644
index 0000000..c1c0e81
--- /dev/null
+++ b/5/9.java
@@ -0,0 +1,73 @@
+import java.util.*;
+
+public class Main {
+
+    public static boolean[] visited = new boolean[9];
+    public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
+
+    // BFS 함수 정의
+    public static void bfs(int start) {
+        Queue<Integer> q = new LinkedList<>();
+        q.offer(start);
+        // 현재 노드를 방문 처리
+        visited[start] = true;
+        // 큐가 빌 때까지 반복
+        while(!q.isEmpty()) {
+            // 큐에서 하나의 원소를 뽑아 출력
+            int x = q.poll();
+            System.out.print(x + " ");
+            // 해당 원소와 연결된, 아직 방문하지 않은 원소들을 큐에 삽입
+            for(int i = 0; i < graph.get(x).size(); i++) {
+                int y = graph.get(x).get(i);
+                if(!visited[y]) {
+                    q.offer(y);
+                    visited[y] = true;
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        // 그래프 초기화
+        for (int i = 0; i < 9; i++) {
+            graph.add(new ArrayList<Integer>());
+        }
+
+        // 노드 1에 연결된 노드 정보 저장 
+        graph.get(1).add(2);
+        graph.get(1).add(3);
+        graph.get(1).add(8);
+        
+        // 노드 2에 연결된 노드 정보 저장 
+        graph.get(2).add(1);
+        graph.get(2).add(7);
+        
+        // 노드 3에 연결된 노드 정보 저장 
+        graph.get(3).add(1);
+        graph.get(3).add(4);
+        graph.get(3).add(5);
+        
+        // 노드 4에 연결된 노드 정보 저장 
+        graph.get(4).add(3);
+        graph.get(4).add(5);
+        
+        // 노드 5에 연결된 노드 정보 저장 
+        graph.get(5).add(3);
+        graph.get(5).add(4);
+        
+        // 노드 6에 연결된 노드 정보 저장 
+        graph.get(6).add(7);
+        
+        // 노드 7에 연결된 노드 정보 저장 
+        graph.get(7).add(2);
+        graph.get(7).add(6);
+        graph.get(7).add(8);
+        
+        // 노드 8에 연결된 노드 정보 저장 
+        graph.get(8).add(1);
+        graph.get(8).add(7);
+
+        bfs(1);
+    }
+
+}
\ No newline at end of file
diff --git a/5/9.py b/5/9.py
index 3dea226..c76d400 100644
--- a/5/9.py
+++ b/5/9.py
@@ -1,6 +1,6 @@
 from collections import deque
 
-# BFS 메서드 정의
+# BFS 함수 정의
 def bfs(graph, start, visited):
     # 큐(Queue) 구현을 위해 deque 라이브러리 사용
     queue = deque([start])
@@ -8,7 +8,7 @@ def bfs(graph, start, visited):
     visited[start] = True
     # 큐가 빌 때까지 반복
     while queue:
-        # 큐에서 하나의 원소를 뽑아 출력하기
+        # 큐에서 하나의 원소를 뽑아 출력
         v = queue.popleft()
         print(v, end=' ')
         # 해당 원소와 연결된, 아직 방문하지 않은 원소들을 큐에 삽입
@@ -17,7 +17,7 @@ def bfs(graph, start, visited):
                 queue.append(i)
                 visited[i] = True
 
-# 각 노드가 연결된 정보를 리스트 자료형으로 표현 (2차원 리스트)
+# 각 노드가 연결된 정보를 리스트 자료형으로 표현(2차원 리스트)
 graph = [
   [],
   [2, 3, 8],
@@ -30,7 +30,7 @@ def bfs(graph, start, visited):
   [1, 7]
 ]
 
-# 각 노드가 방문된 정보를 리스트 자료형으로 표현 (1차원 리스트)
+# 각 노드가 방문된 정보를 리스트 자료형으로 표현(1차원 리스트)
 visited = [False] * 9
 
 # 정의된 BFS 함수 호출
diff --git a/6/1.cpp b/6/1.cpp
new file mode 100644
index 0000000..c80f4e6
--- /dev/null
+++ b/6/1.cpp
@@ -0,0 +1,21 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n = 10;
+int arr[10] = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
+
+int main(void) {
+    for (int i = 0; i < n; i++) {
+        int min_index = i; // 가장 작은 원소의 인덱스 
+        for (int j = i + 1; j < n; j++) {
+            if (arr[min_index] > arr[j]) {
+                min_index = j;
+            }
+        }
+        swap(arr[i], arr[min_index]); // 스와프
+    }
+    for(int i = 0; i < n; i++) {
+        cout << arr[i] << ' ';
+    }
+}
diff --git a/6/1.java b/6/1.java
new file mode 100644
index 0000000..dcdbc8c
--- /dev/null
+++ b/6/1.java
@@ -0,0 +1,28 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+
+        int n = 10;
+        int[] arr = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
+
+        for (int i = 0; i < n; i++) {
+            int min_index = i; // 가장 작은 원소의 인덱스 
+            for (int j = i + 1; j < n; j++) {
+                if (arr[min_index] > arr[j]) {
+                    min_index = j;
+                }
+            }
+            // 스와프
+            int temp = arr[i];
+            arr[i] = arr[min_index];
+            arr[min_index] = temp;
+        }
+
+        for(int i = 0; i < n; i++) {
+            System.out.print(arr[i] + " ");
+        }
+    }
+
+}
diff --git a/6/10.cpp b/6/10.cpp
new file mode 100644
index 0000000..df9d977
--- /dev/null
+++ b/6/10.cpp
@@ -0,0 +1,29 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n;
+vector<int> v;
+
+bool compare(int a, int b) {
+    return a > b;
+}
+
+int main(void) {
+    // N을 입력받기
+    cin >> n;
+
+    // N개의 정수를 입력받아 리스트에 저장
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        v.push_back(x);
+    }
+
+    // 기본 정렬 라이브러리를 이용하여 내림차순 정렬 수행
+    sort(v.begin(), v.end(), compare);
+
+    for(int i = 0; i < n; i++) {
+        cout << v[i] << ' ';
+    }
+}
diff --git a/6/10.java b/6/10.java
new file mode 100644
index 0000000..0f0d29a
--- /dev/null
+++ b/6/10.java
@@ -0,0 +1,25 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N을 입력받기
+        int n = sc.nextInt();
+
+        // N개의 정수를 입력받아 리스트에 저장
+        Integer[] arr = new Integer[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+
+        // 기본 정렬 라이브러리를 이용하여 내림차순 정렬 수행
+        Arrays.sort(arr, Collections.reverseOrder());
+
+        for(int i = 0; i < n; i++) {
+            System.out.print(arr[i] + " ");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/6/10.py b/6/10.py
new file mode 100644
index 0000000..e9387cf
--- /dev/null
+++ b/6/10.py
@@ -0,0 +1,14 @@
+# N 입력 받기
+n = int(input())
+
+# N개의 정수를 입력 받아 리스트에 저장
+array = []
+for i in range(n):
+    array.append(int(input()))
+
+# 파이썬 정렬 라이브러리를 이용하여 내림차순 정렬 수행
+array = sorted(array, reverse=True)
+
+# 정렬이 수행된 결과를 출력
+for i in array:
+    print(i, end=' ')
diff --git a/6/11.cpp b/6/11.cpp
new file mode 100644
index 0000000..90a0d98
--- /dev/null
+++ b/6/11.cpp
@@ -0,0 +1,40 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+class Student {
+public:
+    string name;
+    int score;
+    Student(string name, int score) {
+        this->name = name;
+        this->score = score;
+    }
+    // 정렬 기준은 '점수가 낮은 순서'
+    bool operator <(Student &other) {
+        return this->score < other.score; 
+    }
+};
+
+int n;
+vector<Student> v;
+
+int main(void) {
+    // N을 입력받기
+    cin >> n;
+
+    // N명의 학생 정보를 입력받아 리스트에 저장
+    for (int i = 0; i < n; i++) {
+        string name;
+        int score;
+        cin >> name >> score;
+        v.push_back(Student(name, score));
+    }
+    
+    sort(v.begin(), v.end());
+
+    // 정렬이 수행된 결과를 출력
+    for(int i = 0; i < n; i++) {
+        cout << v[i].name << ' ';
+    }
+}
\ No newline at end of file
diff --git a/6/11.java b/6/11.java
new file mode 100644
index 0000000..3477427
--- /dev/null
+++ b/6/11.java
@@ -0,0 +1,53 @@
+import java.util.*;
+
+class Student implements Comparable<Student> {
+
+    private String name;
+    private int score;
+
+    public Student(String name, int score) {
+        this.name = name;
+        this.score = score;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public int getScore() {
+        return this.score;
+    }
+
+    // 정렬 기준은 '점수가 낮은 순서'
+    @Override
+    public int compareTo(Student other) {
+        if (this.score < other.score) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N을 입력받기
+        int n = sc.nextInt();
+
+        // N명의 학생 정보를 입력받아 리스트에 저장
+        List<Student> students = new ArrayList<>();
+        for (int i = 0; i < n; i++) {
+            String name = sc.next();
+            int score = sc.nextInt();
+            students.add(new Student(name, score));
+        }
+
+        Collections.sort(students);
+
+        for (int i = 0; i < students.size(); i++) {
+            System.out.print(students.get(i).getName() + " ");
+        }
+    }
+}
\ No newline at end of file
diff --git a/6/11.py b/6/11.py
new file mode 100644
index 0000000..9f1cf0d
--- /dev/null
+++ b/6/11.py
@@ -0,0 +1,16 @@
+# N 입력 받기
+n = int(input())
+
+# N명의 학생 정보를 입력 받아 리스트에 저장
+array = []
+for i in range(n):
+    input_data = input().split()
+    # 이름은 문자열 그대로, 점수는 정수형으로 변환하여 저장
+    array.append((input_data[0], int(input_data[1])))
+
+# 키(Key)를 이용하여, 점수를 기준으로 정렬
+array = sorted(array, key=lambda student: student[1])
+
+# 정렬이 수행된 결과를 출력
+for student in array:
+    print(student[0], end=' ')
diff --git a/6/12.cpp b/6/12.cpp
new file mode 100644
index 0000000..1d7b69b
--- /dev/null
+++ b/6/12.cpp
@@ -0,0 +1,46 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, k;
+vector<int> a, b;
+
+bool compare(int x, int y) {
+    return x > y;
+}
+
+int main(void) {
+    // N과 K를 입력받기
+    cin >> n >> k;
+    // 배열 A의 모든 원소를 입력받기
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        a.push_back(x);
+    }
+    // 배열 B의 모든 원소를 입력받기
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        b.push_back(x);
+    }
+    // 배열 A는 오름차순 정렬 수행
+    sort(a.begin(), a.end());
+    // 배열 B는 내림차순 정렬 수행
+    sort(b.begin(), b.end(), compare);
+
+    // 첫 번째 인덱스부터 확인하며, 두 배열의 원소를 최대 K번 비교 
+    for (int i = 0; i < k; i++) {
+        // A의 원소가 B의 원소보다 작은 경우
+        if (a[i] < b[i]) swap(a[i], b[i]); // 두 원소를 교체
+        // A의 원소가 B의 원소보다 크거나 같을 때, 반복문을 탈출
+        else break;
+    }
+
+    // 배열 A의 모든 원소의 합을 출력
+    long long result = 0;
+    for (int i = 0; i < n; i++) {
+        result += a[i];
+    }
+    cout << result << '\n';
+}
diff --git a/6/12.java b/6/12.java
new file mode 100644
index 0000000..2f1a849
--- /dev/null
+++ b/6/12.java
@@ -0,0 +1,49 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // N과 K를 입력받기
+        int n = sc.nextInt();
+        int k = sc.nextInt();
+
+        // 배열 A의 모든 원소를 입력받기
+        Integer[] a = new Integer[n];
+        for (int i = 0; i < n; i++) {
+            a[i] = sc.nextInt();
+        }
+        // 배열 B의 모든 원소를 입력받기
+        Integer[] b = new Integer[n];
+        for (int i = 0; i < n; i++) {
+            b[i] = sc.nextInt();
+        }
+
+        // 배열 A는 오름차순 정렬 수행
+        Arrays.sort(a);
+        // 배열 B는 내림차순 정렬 수행
+        Arrays.sort(b, Collections.reverseOrder());
+
+        // 첫 번째 인덱스부터 확인하며, 두 배열의 원소를 최대 K번 비교 
+        for (int i = 0; i < k; i++) {
+            // A의 원소가 B의 원소보다 작은 경우
+            if (a[i] < b[i]) {
+                // 두 원소를 교체
+                int temp = a[i];
+                a[i] = b[i];
+                b[i] = temp;
+            }
+            // A의 원소가 B의 원소보다 크거나 같을 때, 반복문을 탈출
+            else break;
+        }
+
+        // 배열 A의 모든 원소의 합을 출력
+        long result = 0;
+        for (int i = 0; i < n; i++) {
+            result += a[i];
+        }
+        System.out.println(result);
+    }
+
+}
\ No newline at end of file
diff --git a/6/12.py b/6/12.py
new file mode 100644
index 0000000..bc0fc69
--- /dev/null
+++ b/6/12.py
@@ -0,0 +1,17 @@
+n, k = map(int, input().split()) # N과 K를 입력 받기
+a = list(map(int, input().split())) # 배열 A의 모든 원소를 입력받기
+b = list(map(int, input().split())) # 배열 B의 모든 원소를 입력받기
+
+a.sort() # 배열 A는 오름차순 정렬 수행
+b.sort(reverse=True) # 배열 B는 내림차순 정렬 수행
+
+# 첫 번째 인덱스부터 확인하며, 두 배열의 원소를 최대 K번 비교
+for i in range(k):
+    # A의 원소가 B의 원소보다 작은 경우
+    if a[i] < b[i]:
+        # 두 원소를 교체
+        a[i], b[i] = b[i], a[i]
+    else: # A의 원소가 B의 원소보다 크거나 같을 때, 반복문을 탈출
+        break
+
+print(sum(a)) # 배열 A의 모든 원소의 합을 출력
diff --git a/6/2.cpp b/6/2.cpp
new file mode 100644
index 0000000..c45200c
--- /dev/null
+++ b/6/2.cpp
@@ -0,0 +1,10 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int arr[2] = {3, 5};
+
+int main(void) {
+    swap(arr[0], arr[1]);
+    cout << arr[0] << ' ' << arr[1] << '\n';
+}
diff --git a/6/2.java b/6/2.java
new file mode 100644
index 0000000..b9f5fbb
--- /dev/null
+++ b/6/2.java
@@ -0,0 +1,17 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+
+        int[] arr = {3, 5};
+
+        // 스와프(Swap)
+        int temp = arr[0];
+        arr[0] = arr[1];
+        arr[1] = temp;
+
+        System.out.println(arr[0] + " " + arr[1]);
+    }
+
+}
diff --git a/6/2.py b/6/2.py
index 8c44aea..216ebbf 100644
--- a/6/2.py
+++ b/6/2.py
@@ -1,10 +1,5 @@
-array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]
-
-for i in range(1, len(array)):
-    for j in range(i, 0, -1): # 인덱스 i부터 1까지 1씩 감소하며 반복하는 문법
-        if array[j] < array[j - 1]: # 한 칸씩 왼쪽으로 이동
-            array[j], array[j - 1] = array[j - 1], array[j]
-        else: # 자기보다 작은 데이터를 만나면 그 위치에서 멈춤
-            break
+# 0 인덱스와 1 인덱스의 원소 교체하기
+array = [3, 5]
+array[0], array[1] = array[1], array[0]
 
 print(array)
diff --git a/6/3.cpp b/6/3.cpp
new file mode 100644
index 0000000..51c80a6
--- /dev/null
+++ b/6/3.cpp
@@ -0,0 +1,23 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n = 10;
+int arr[10] = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
+
+int main(void) {
+    for (int i = 1; i < n; i++) {
+        // 인덱스 i부터 1까지 감소하며 반복하는 문법
+        for (int j = i; j > 0; j--) {
+            // 한 칸씩 왼쪽으로 이동
+            if (arr[j] < arr[j - 1]) {
+                swap(arr[j], arr[j - 1]);
+            }
+            // 자기보다 작은 데이터를 만나면 그 위치에서 멈춤
+            else break;
+        }
+    }
+    for(int i = 0; i < n; i++) {
+        cout << arr[i] << ' ';
+    }
+}
\ No newline at end of file
diff --git a/6/3.java b/6/3.java
new file mode 100644
index 0000000..5168ba8
--- /dev/null
+++ b/6/3.java
@@ -0,0 +1,30 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+
+        int n = 10;
+        int[] arr = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
+
+        for (int i = 1; i < n; i++) {
+            // 인덱스 i부터 1까지 감소하며 반복하는 문법
+            for (int j = i; j > 0; j--) {
+                // 한 칸씩 왼쪽으로 이동
+                if (arr[j] < arr[j - 1]) {
+                    // 스와프(Swap)
+                    int temp = arr[j];
+                    arr[j] = arr[j - 1];
+                    arr[j - 1] = temp;
+                }
+                // 자기보다 작은 데이터를 만나면 그 위치에서 멈춤
+                else break;
+            }
+        }
+
+        for(int i = 0; i < n; i++) {
+            System.out.print(arr[i] + " ");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/6/3.py b/6/3.py
index fba9349..8c44aea 100644
--- a/6/3.py
+++ b/6/3.py
@@ -1,25 +1,10 @@
-array = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8]
+array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]
 
-def quick_sort(array, start, end):
-    if start >= end: # 원소가 1개인 경우 종료
-        return
-    pivot = start # 피벗은 첫 번째 원소
-    left = start + 1
-    right = end
-    while(left <= right):
-        # 피벗보다 큰 데이터를 찾을 때까지 반복 
-        while(left <= end and array[left] <= array[pivot]):
-            left += 1
-        # 피벗보다 작은 데이터를 찾을 때까지 반복
-        while(right > start and array[right] >= array[pivot]):
-            right -= 1
-        if(left > right): # 엇갈렸다면 작은 데이터와 피벗을 교체
-            array[right], array[pivot] = array[pivot], array[right]
-        else: # 엇갈리지 않았다면 작은 데이터와 큰 데이터를 교체
-            array[left], array[right] = array[right], array[left]
-    # 분할 이후 왼쪽 부분과 오른쪽 부분에서 각각 정렬 수행
-    quick_sort(array, start, right - 1)
-    quick_sort(array, right + 1, end)
+for i in range(1, len(array)):
+    for j in range(i, 0, -1): # 인덱스 i부터 1까지 1씩 감소하며 반복하는 문법
+        if array[j] < array[j - 1]: # 한 칸씩 왼쪽으로 이동
+            array[j], array[j - 1] = array[j - 1], array[j]
+        else: # 자기보다 작은 데이터를 만나면 그 위치에서 멈춤
+            break
 
-quick_sort(array, 0, len(array) - 1)
 print(array)
diff --git a/6/4.cpp b/6/4.cpp
new file mode 100644
index 0000000..c9f6a40
--- /dev/null
+++ b/6/4.cpp
@@ -0,0 +1,33 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n = 10;
+int arr[10] = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
+
+void quickSort(int* arr, int start, int end) {
+    if (start >= end) return; // 원소가 1개인 경우 종료
+    int pivot = start; // 피벗은 첫 번째 원소
+    int left = start + 1;
+    int right = end;
+    while (left <= right) {
+        // 피벗보다 큰 데이터를 찾을 때까지 반복
+        while (left <= end && arr[left] <= arr[pivot]) left++;
+        // 피벗보다 작은 데이터를 찾을 때까지 반복
+        while (right > start && arr[right] >= arr[pivot]) right--;
+        // 엇갈렸다면 작은 데이터와 피벗을 교체
+        if (left > right) swap(arr[pivot], arr[right]);
+        // 엇갈리지 않았다면 작은 데이터와 큰 데이터를 교체
+        else swap(arr[left], arr[right]);
+    }
+    // 분할 이후 왼쪽 부분과 오른쪽 부분에서 각각 정렬 수행
+    quickSort(arr, start, right - 1);
+    quickSort(arr, right + 1, end);
+}
+
+int main(void) {
+    quickSort(arr, 0, n - 1);
+    for (int i = 0; i < n; i++) {
+        cout << arr[i] << ' ';
+    }
+}
\ No newline at end of file
diff --git a/6/4.java b/6/4.java
new file mode 100644
index 0000000..10449f6
--- /dev/null
+++ b/6/4.java
@@ -0,0 +1,44 @@
+import java.util.*;
+
+public class Main {
+
+    public static void quickSort(int[] arr, int start, int end) {
+        if (start >= end) return; // 원소가 1개인 경우 종료
+        int pivot = start; // 피벗은 첫 번째 원소
+        int left = start + 1;
+        int right = end;
+        while (left <= right) {
+            // 피벗보다 큰 데이터를 찾을 때까지 반복
+            while (left <= end && arr[left] <= arr[pivot]) left++;
+            // 피벗보다 작은 데이터를 찾을 때까지 반복
+            while (right > start && arr[right] >= arr[pivot]) right--;
+            // 엇갈렸다면 작은 데이터와 피벗을 교체
+            if (left > right) {
+                int temp = arr[pivot];
+                arr[pivot] = arr[right];
+                arr[right] = temp;
+            }
+            // 엇갈리지 않았다면 작은 데이터와 큰 데이터를 교체
+            else {
+                int temp = arr[left];
+                arr[left] = arr[right];
+                arr[right] = temp;
+            }
+        }
+        // 분할 이후 왼쪽 부분과 오른쪽 부분에서 각각 정렬 수행
+        quickSort(arr, start, right - 1);
+        quickSort(arr, right + 1, end);
+    }
+
+    public static void main(String[] args) {
+        int n = 10;
+        int[] arr = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
+
+        quickSort(arr, 0, n - 1);
+
+        for(int i = 0; i < n; i++) {
+            System.out.print(arr[i] + " ");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/6/4.py b/6/4.py
index 585a379..fba9349 100644
--- a/6/4.py
+++ b/6/4.py
@@ -1,11 +1,25 @@
-# 모든 원소의 값이 0보다 크거나 같다고 가정
-array = [7, 5, 9, 0, 3, 1, 6, 2, 9, 1, 4, 8, 0, 5, 2]
-# 모든 범위를 포함하는 리스트 선언 (모든 값은 0으로 초기화)
-count = [0] * (max(array) + 1)
+array = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8]
 
-for i in range(len(array)):
-    count[array[i]] += 1 # 각 데이터에 해당하는 인덱스의 값 증가
+def quick_sort(array, start, end):
+    if start >= end: # 원소가 1개인 경우 종료
+        return
+    pivot = start # 피벗은 첫 번째 원소
+    left = start + 1
+    right = end
+    while(left <= right):
+        # 피벗보다 큰 데이터를 찾을 때까지 반복 
+        while(left <= end and array[left] <= array[pivot]):
+            left += 1
+        # 피벗보다 작은 데이터를 찾을 때까지 반복
+        while(right > start and array[right] >= array[pivot]):
+            right -= 1
+        if(left > right): # 엇갈렸다면 작은 데이터와 피벗을 교체
+            array[right], array[pivot] = array[pivot], array[right]
+        else: # 엇갈리지 않았다면 작은 데이터와 큰 데이터를 교체
+            array[left], array[right] = array[right], array[left]
+    # 분할 이후 왼쪽 부분과 오른쪽 부분에서 각각 정렬 수행
+    quick_sort(array, start, right - 1)
+    quick_sort(array, right + 1, end)
 
-for i in range(len(count)): # 리스트에 기록된 정렬 정보 확인
-    for j in range(count[i]):
-        print(i, end=' ') # 띄어쓰기를 구분으로 등장한 횟수만큼 인덱스 출력
+quick_sort(array, 0, len(array) - 1)
+print(array)
diff --git a/6/5.py b/6/5.py
index 0be7f1a..5a862c8 100644
--- a/6/5.py
+++ b/6/5.py
@@ -1,4 +1,17 @@
-array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]
+array = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8]
 
-result = sorted(array)
-print(result)
+def quick_sort(array):
+    # 리스트가 하나 이하의 원소만을 담고 있다면 종료
+    if len(array) <= 1:
+        return array
+
+    pivot = array[0] # 피벗은 첫 번째 원소
+    tail = array[1:] # 피벗을 제외한 리스트
+
+    left_side = [x for x in tail if x <= pivot] # 분할된 왼쪽 부분
+    right_side = [x for x in tail if x > pivot] # 분할된 오른쪽 부분
+
+    # 분할 이후 왼쪽 부분과 오른쪽 부분에서 각각 정렬을 수행하고, 전체 리스트를 반환
+    return quick_sort(left_side) + [pivot] + quick_sort(right_side)
+
+print(quick_sort(array))
diff --git a/6/6.cpp b/6/6.cpp
new file mode 100644
index 0000000..f305e16
--- /dev/null
+++ b/6/6.cpp
@@ -0,0 +1,21 @@
+#include <bits/stdc++.h>
+#define MAX_VALUE 9
+
+using namespace std;
+
+int n = 15;
+// 모든 원소의 값이 0보다 크거나 같다고 가정
+int arr[15] = {7, 5, 9, 0, 3, 1, 6, 2, 9, 1, 4, 8, 0, 5, 2};
+// 모든 범위를 포함하는 배열 선언(모든 값은 0으로 초기화)
+int cnt[MAX_VALUE + 1];
+
+int main(void) {
+    for (int i = 0; i < n; i++) {
+        cnt[arr[i]] += 1; // 각 데이터에 해당하는 인덱스의 값 증가
+    }
+    for (int i = 0; i <= MAX_VALUE; i++) { // 배열에 기록된 정렬 정보 확인
+        for (int j = 0; j < cnt[i]; j++) {
+            cout << i << ' '; // 띄어쓰기를 기준으로 등장한 횟수만큼 인덱스 출력
+        }
+    }
+}
\ No newline at end of file
diff --git a/6/6.java b/6/6.java
new file mode 100644
index 0000000..e8661fc
--- /dev/null
+++ b/6/6.java
@@ -0,0 +1,25 @@
+import java.util.*;
+
+public class Main {
+	
+    public static final int MAX_VALUE = 9;
+
+    public static void main(String[] args) {
+    	
+        int n = 15;
+        // 모든 원소의 값이 0보다 크거나 같다고 가정
+        int[] arr = {7, 5, 9, 0, 3, 1, 6, 2, 9, 1, 4, 8, 0, 5, 2};
+        // 모든 범위를 포함하는 배열 선언(모든 값은 0으로 초기화)
+        int[] cnt = new int[MAX_VALUE + 1];
+
+        for (int i = 0; i < n; i++) {
+            cnt[arr[i]] += 1; // 각 데이터에 해당하는 인덱스의 값 증가
+        }
+        for (int i = 0; i <= MAX_VALUE; i++) { // 배열에 기록된 정렬 정보 확인
+            for (int j = 0; j < cnt[i]; j++) {
+                System.out.print(i + " "); // 띄어쓰기를 기준으로 등장한 횟수만큼 인덱스 출력
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/6/6.py b/6/6.py
index 97904b2..585a379 100644
--- a/6/6.py
+++ b/6/6.py
@@ -1,7 +1,11 @@
-array = [('바나나', 2), ('사과', 5), ('당근', 3)]
+# 모든 원소의 값이 0보다 크거나 같다고 가정
+array = [7, 5, 9, 0, 3, 1, 6, 2, 9, 1, 4, 8, 0, 5, 2]
+# 모든 범위를 포함하는 리스트 선언 (모든 값은 0으로 초기화)
+count = [0] * (max(array) + 1)
 
-def setting(data):
-    return data[1]
+for i in range(len(array)):
+    count[array[i]] += 1 # 각 데이터에 해당하는 인덱스의 값 증가
 
-result = sorted(array, key=setting)
-print(result)
+for i in range(len(count)): # 리스트에 기록된 정렬 정보 확인
+    for j in range(count[i]):
+        print(i, end=' ') # 띄어쓰기를 구분으로 등장한 횟수만큼 인덱스 출력
diff --git a/6/7.cpp b/6/7.cpp
new file mode 100644
index 0000000..fa665a0
--- /dev/null
+++ b/6/7.cpp
@@ -0,0 +1,13 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n = 10;
+int arr[10] = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
+
+int main(void) {
+    sort(arr, arr + n);
+    for (int i = 0; i < n; i++) {
+        cout << arr[i] << ' ';
+    }
+}
\ No newline at end of file
diff --git a/6/7.java b/6/7.java
new file mode 100644
index 0000000..8ca180a
--- /dev/null
+++ b/6/7.java
@@ -0,0 +1,17 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+    	
+        int n = 10;
+        int[] arr = {7, 5, 9, 0, 3, 1, 6, 2, 4, 8};
+
+        Arrays.sort(arr);
+
+        for(int i = 0; i < n; i++) {
+            System.out.print(arr[i] + " ");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/6/7.py b/6/7.py
index f0105a4..0be7f1a 100644
--- a/6/7.py
+++ b/6/7.py
@@ -1,14 +1,4 @@
-# N 입력 받기
-n = int(input())
+array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]
 
-# N개의 정수를 입력 받아 리스트에 저장
-array = []
-for i in range(n):
-    array.append(int(input()))
-
-# 파이썬 정렬 라이브러리를 이용하여 정렬 수행
-array = sorted(array, reverse=True)
-
-# 정렬이 수행된 결과를 출력
-for i in array:
-    print(i, end=' ')
+result = sorted(array)
+print(result)
diff --git a/6/8.py b/6/8.py
index 9f1cf0d..e5f32c8 100644
--- a/6/8.py
+++ b/6/8.py
@@ -1,16 +1,4 @@
-# N 입력 받기
-n = int(input())
+array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]
 
-# N명의 학생 정보를 입력 받아 리스트에 저장
-array = []
-for i in range(n):
-    input_data = input().split()
-    # 이름은 문자열 그대로, 점수는 정수형으로 변환하여 저장
-    array.append((input_data[0], int(input_data[1])))
-
-# 키(Key)를 이용하여, 점수를 기준으로 정렬
-array = sorted(array, key=lambda student: student[1])
-
-# 정렬이 수행된 결과를 출력
-for student in array:
-    print(student[0], end=' ')
+array.sort()
+print(array)
diff --git a/6/9.cpp b/6/9.cpp
new file mode 100644
index 0000000..d29e5e7
--- /dev/null
+++ b/6/9.cpp
@@ -0,0 +1,30 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+class Fruit {
+public:
+    string name;
+    int score;
+    Fruit(string name, int score) {
+        this->name = name;
+        this->score = score;
+    }
+    // 정렬 기준은 '점수가 낮은 순서'
+    bool operator <(Fruit &other) {
+        return this->score < other.score; 
+    }
+};
+
+int main(void) {
+    int n = 3;
+    Fruit fruits[] = {
+        Fruit("바나나", 2),
+        Fruit("사과", 5),
+        Fruit("당근", 3)
+    };
+    sort(fruits, fruits + n);
+    for(int i = 0; i < n; i++) {
+        cout << '(' << fruits[i].name << ',' << fruits[i].score << ')' << ' ';
+    }
+}
\ No newline at end of file
diff --git a/6/9.java b/6/9.java
new file mode 100644
index 0000000..8d56f38
--- /dev/null
+++ b/6/9.java
@@ -0,0 +1,46 @@
+import java.util.*;
+
+class Fruit implements Comparable<Fruit> {
+
+    private String name;
+    private int score;
+
+    public Fruit(String name, int score) {
+        this.name = name;
+        this.score = score;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public int getScore() {
+        return this.score;
+    }
+
+    // 정렬 기준은 '점수가 낮은 순서'
+    @Override
+    public int compareTo(Fruit other) {
+        if (this.score < other.score) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+
+    public static void main(String[] args) {
+        List<Fruit> fruits = new ArrayList<>();
+
+        fruits.add(new Fruit("바나나", 2));
+        fruits.add(new Fruit("사과", 5));
+        fruits.add(new Fruit("당근", 3));
+
+        Collections.sort(fruits);
+
+        for (int i = 0; i < fruits.size(); i++) {
+            System.out.print("(" + fruits.get(i).getName() + "," + fruits.get(i).getScore() + ") ");
+        }
+    }
+}
\ No newline at end of file
diff --git a/6/9.py b/6/9.py
index 663db30..97904b2 100644
--- a/6/9.py
+++ b/6/9.py
@@ -1,15 +1,7 @@
-# N 입력 받기
-n = int(input())
+array = [('바나나', 2), ('사과', 5), ('당근', 3)]
 
-count = [0] * 10001
-result = -1 # 가장 많이 가지고 있는 신발 번호
-max_value = 0 # 가장 많이 가지고 있는 신발 번호의 신발 개수
-
-for i in range(n):
-    a = int(input())
-    count[a] += 1
-    if max_value < count[a]:
-        max_value = count[a]
-        result = a # 가장 많이 가지고 있는 신발 번호 기록
+def setting(data):
+    return data[1]
 
+result = sorted(array, key=setting)
 print(result)
diff --git a/7/1.cpp b/7/1.cpp
new file mode 100644
index 0000000..fa40e19
--- /dev/null
+++ b/7/1.cpp
@@ -0,0 +1,34 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 순차 탐색 소스코드 구현
+int sequantialSearch(int n, string target, vector<string> arr) {
+    // 각 원소를 하나씩 확인하며
+    for (int i = 0; i < n; i++) {
+        // 현재의 원소가 찾고자 하는 원소와 동일한 경우
+        if (arr[i] == target) {
+            return i + 1; // 현재의 위치 반환 (인덱스는 0부터 시작하므로 1 더하기)
+        }
+    }
+    return -1; // 원소를 찾지 못한 경우 -1 반환
+}
+
+int n; // 원소의 개수
+string target; // 찾고자 하는 문자열
+vector<string> arr;
+
+int main(void) {
+    cout << "생성할 원소 개수를 입력한 다음 한 칸 띄고 찾을 문자열을 입력하세요." << '\n';
+    cin >> n >> target;
+    
+    cout << "앞서 적은 원소 개수만큼 문자열을 입력하세요. 구분은 띄어쓰기 한 칸으로 합니다." << '\n';
+    for (int i = 0; i < n; i++) {
+        string x;
+        cin >> x;
+        arr.push_back(x);
+    }
+
+    // 순차 탐색 수행 결과 출력
+    cout << sequantialSearch(n, target, arr) << '\n';
+}
\ No newline at end of file
diff --git a/7/1.java b/7/1.java
new file mode 100644
index 0000000..f929b65
--- /dev/null
+++ b/7/1.java
@@ -0,0 +1,37 @@
+import java.util.*;
+
+public class Main {
+
+    // 순차 탐색 소스코드 구현
+    public static int sequantialSearch(int n, String target, String[] arr) {
+        // 각 원소를 하나씩 확인하며
+        for (int i = 0; i < n; i++) {
+        	System.out.println(arr[i]);
+            // 현재의 원소가 찾고자 하는 원소와 동일한 경우
+            if (arr[i].equals(target)) {
+                return i + 1; // 현재의 위치 반환 (인덱스는 0부터 시작하므로 1 더하기)
+            }
+        }
+        return -1; // 원소를 찾지 못한 경우 -1 반환
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        System.out.println("생성할 원소 개수를 입력한 다음 한 칸 띄고 찾을 문자열을 입력하세요.");
+        // 원소의 개수
+        int n = sc.nextInt();
+        // 찾고자 하는 문자열
+        String target = sc.next();
+
+        System.out.println("앞서 적은 원소 개수만큼 문자열을 입력하세요. 구분은 띄어쓰기 한 칸으로 합니다.");
+        String[] arr = new String[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.next();
+        }
+
+        // 순차 탐색 수행 결과 출력
+        System.out.println(sequantialSearch(n, target, arr));
+    }
+
+}
\ No newline at end of file
diff --git a/7/1.py b/7/1.py
index aef93e1..0122f30 100644
--- a/7/1.py
+++ b/7/1.py
@@ -5,6 +5,7 @@ def sequential_search(n, target, array):
         # 현재의 원소가 찾고자 하는 원소와 동일한 경우
         if array[i] == target:
             return i + 1 # 현재의 위치 반환 (인덱스는 0부터 시작하므로 1 더하기)
+    return -1 # 원소를 찾지 못한 경우 -1 반환
 
 print("생성할 원소 개수를 입력한 다음 한 칸 띄고 찾을 문자열을 입력하세요.")
 input_data = input().split()
diff --git a/7/2.cpp b/7/2.cpp
new file mode 100644
index 0000000..85a7424
--- /dev/null
+++ b/7/2.cpp
@@ -0,0 +1,37 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 이진 탐색 소스코드 구현(재귀 함수)
+int binarySearch(vector<int>& arr, int target, int start, int end) {
+    if (start > end) return -1;
+    int mid = (start + end) / 2;
+    // 찾은 경우 중간점 인덱스 반환
+    if (arr[mid] == target) return mid;
+    // 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
+    else if (arr[mid] > target) return binarySearch(arr, target, start, mid - 1);
+    // 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
+    else return binarySearch(arr, target, mid + 1, end);
+}
+
+int n, target;
+vector<int> arr;
+
+int main(void) {
+    // n(원소의 개수)와 target(찾고자 하는 값)을 입력받기 
+    cin >> n >> target;
+    // 전체 원소 입력받기 
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+    // 이진 탐색 수행 결과 출력 
+    int result = binarySearch(arr, target, 0, n - 1);
+    if (result == -1) {
+        cout << "원소가 존재하지 않습니다." << '\n';
+    }
+    else {
+        cout << result + 1 << '\n';
+    }
+}
diff --git a/7/2.java b/7/2.java
new file mode 100644
index 0000000..5530fdf
--- /dev/null
+++ b/7/2.java
@@ -0,0 +1,40 @@
+import java.util.*;
+
+public class Main {
+
+    // 이진 탐색 소스코드 구현(재귀 함수)
+    public static int binarySearch(int[] arr, int target, int start, int end) {
+        if (start > end) return -1;
+        int mid = (start + end) / 2;
+        // 찾은 경우 중간점 인덱스 반환
+        if (arr[mid] == target) return mid;
+        // 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
+        else if (arr[mid] > target) return binarySearch(arr, target, start, mid - 1);
+        // 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
+        else return binarySearch(arr, target, mid + 1, end);
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        // 원소의 개수(n)와 찾고자 하는 값(target)을 입력받기 
+        int n = sc.nextInt();
+        int target = sc.nextInt();
+
+        // 전체 원소 입력받기 
+        int[] arr = new int[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+
+        // 이진 탐색 수행 결과 출력 
+        int result = binarySearch(arr, target, 0, n - 1);
+        if (result == -1) {
+            System.out.println("원소가 존재하지 않습니다.");
+        }
+        else {
+            System.out.println(result + 1);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/7/2.py b/7/2.py
index 4e38ce7..206d704 100644
--- a/7/2.py
+++ b/7/2.py
@@ -9,11 +9,11 @@ def binary_search(array, target, start, end):
     # 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
     elif array[mid] > target:
         return binary_search(array, target, start, mid - 1)
-    # 중간점의 값보다 찾고자 하는 값이 작은 경우 오른쪽 확인
+    # 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
     else:
         return binary_search(array, target, mid + 1, end)
 
-# n(원소의 개수)과 target(찾고자 하는 문자열)을 입력 받기
+# n(원소의 개수)과 target(찾고자 하는 값)을 입력 받기
 n, target = list(map(int, input().split()))
 # 전체 원소 입력 받기
 array = list(map(int, input().split()))
diff --git a/7/3.cpp b/7/3.cpp
new file mode 100644
index 0000000..c86ab20
--- /dev/null
+++ b/7/3.cpp
@@ -0,0 +1,39 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 이진 탐색 소스코드 구현(반복문)
+int binarySearch(vector<int>& arr, int target, int start, int end) {
+    while (start <= end) {
+        int mid = (start + end) / 2;
+        // 찾은 경우 중간점 인덱스 반환
+        if (arr[mid] == target) return mid;
+        // 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
+        else if (arr[mid] > target) end = mid - 1;
+        // 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
+        else start = mid + 1; 
+    }
+    return -1;
+}
+
+int n, target;
+vector<int> arr;
+
+int main(void) {
+    // n(원소의 개수)와 target(찾고자 하는 값)을 입력 받기 
+    cin >> n >> target;
+    // 전체 원소 입력 받기 
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+    // 이진 탐색 수행 결과 출력 
+    int result = binarySearch(arr, target, 0, n - 1);
+    if (result == -1) {
+        cout << "원소가 존재하지 않습니다." << '\n';
+    }
+    else {
+        cout << result + 1 << '\n';
+    }
+}
diff --git a/7/3.java b/7/3.java
new file mode 100644
index 0000000..ca57080
--- /dev/null
+++ b/7/3.java
@@ -0,0 +1,42 @@
+import java.util.*;
+
+public class Main {
+
+    // 이진 탐색 소스코드 구현(반복문)
+    public static int binarySearch(int[] arr, int target, int start, int end) {
+        while (start <= end) {
+            int mid = (start + end) / 2;
+            // 찾은 경우 중간점 인덱스 반환
+            if (arr[mid] == target) return mid;
+            // 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
+            else if (arr[mid] > target) end = mid - 1;
+            // 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
+            else start = mid + 1; 
+        }
+        return -1;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        // 원소의 개수(n)와 찾고자 하는 값(target)을 입력받기 
+        int n = sc.nextInt();
+        int target = sc.nextInt();
+
+        // 전체 원소 입력받기 
+        int[] arr = new int[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+
+        // 이진 탐색 수행 결과 출력 
+        int result = binarySearch(arr, target, 0, n - 1);
+        if (result == -1) {
+            System.out.println("원소가 존재하지 않습니다.");
+        }
+        else {
+            System.out.println(result + 1);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/7/3.py b/7/3.py
index c98647f..449de3d 100644
--- a/7/3.py
+++ b/7/3.py
@@ -8,12 +8,12 @@ def binary_search(array, target, start, end):
         # 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
         elif array[mid] > target:
             end = mid - 1
-        # 중간점의 값보다 찾고자 하는 값이 작은 경우 오른쪽 확인
+        # 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
         else:
             start = mid + 1
     return None
 
-# n(원소의 개수)과 target(찾고자 하는 문자열)을 입력 받기
+# n(원소의 개수)과 target(찾고자 하는 값)을 입력 받기
 n, target = list(map(int, input().split()))
 # 전체 원소 입력 받기
 array = list(map(int, input().split()))
diff --git a/7/5.cpp b/7/5.cpp
new file mode 100644
index 0000000..7c63a08
--- /dev/null
+++ b/7/5.cpp
@@ -0,0 +1,54 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 이진 탐색 소스코드 구현(반복문)
+int binarySearch(vector<int>& arr, int target, int start, int end) {
+    while (start <= end) {
+        int mid = (start + end) / 2;
+        // 찾은 경우 중간점 인덱스 반환
+        if (arr[mid] == target) return mid;
+        // 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
+        else if (arr[mid] > target) end = mid - 1;
+        // 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
+        else start = mid + 1; 
+    }
+    return -1;
+}
+
+// N(가게의 부품 개수)와 M(손님이 확인 요청한 부품 개수)
+int n, m;
+// 가게에 있는 전체 부품 번호들
+vector<int> arr;
+// 손님이 확인 요청한 부품 번호들
+vector<int> targets;
+
+int main(void) {
+    cin >> n;
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+    
+    // 이진 탐색을 수행하기 위해 사전에 정렬 수행
+    sort(arr.begin(), arr.end());
+    
+    cin >> m;
+    for (int i = 0; i < m; i++) {
+        int target;
+        cin >> target;
+        targets.push_back(target);
+    }
+    // 손님이 확인 요청한 부품 번호를 하나씩 확인
+    for (int i = 0; i < m; i++) {
+        // 해당 부품이 존재하는지 확인
+        int result = binarySearch(arr, targets[i], 0, n - 1);
+        if (result != -1) {
+            cout << "yes" << ' ';
+        }
+        else {
+            cout << "no" << ' ';
+        }
+    }
+}
diff --git a/7/5.java b/7/5.java
new file mode 100644
index 0000000..b3b8a45
--- /dev/null
+++ b/7/5.java
@@ -0,0 +1,52 @@
+import java.util.*;
+
+public class Main {
+
+    // 이진 탐색 소스코드 구현(반복문)
+    public static int binarySearch(int[] arr, int target, int start, int end) {
+        while (start <= end) {
+            int mid = (start + end) / 2;
+            // 찾은 경우 중간점 인덱스 반환
+            if (arr[mid] == target) return mid;
+            // 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인
+            else if (arr[mid] > target) end = mid - 1;
+            // 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인
+            else start = mid + 1; 
+        }
+        return -1;
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        // N(가게의 부품 개수)
+        int n = sc.nextInt();
+        int[] arr = new int[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+        
+        // 이진 탐색을 수행하기 위해 사전에 정렬 수행
+        Arrays.sort(arr);
+
+        // M(손님이 확인 요청한 부품 개수)
+        int m = sc.nextInt();
+        int[] targets = new int[m];
+        for (int i = 0; i < m; i++) {
+            targets[i] = sc.nextInt();
+        }
+
+        // 손님이 확인 요청한 부품 번호를 하나씩 확인
+        for (int i = 0; i < m; i++) {
+            // 해당 부품이 존재하는지 확인
+            int result = binarySearch(arr, targets[i], 0, n - 1);
+            if (result != -1) {
+                System.out.print("yes ");
+            }
+            else {
+                System.out.print("no ");
+            }
+        }
+    }
+
+}
diff --git a/7/6.cpp b/7/6.cpp
new file mode 100644
index 0000000..ae44b53
--- /dev/null
+++ b/7/6.cpp
@@ -0,0 +1,33 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// N(가게의 부품 개수)와 M(손님이 확인 요청한 부품 개수)
+int n, m;
+int arr[1000001];
+vector<int> targets;
+
+int main(void) {
+    cin >> n;
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr[x] = 1;
+    }
+    cin >> m;
+    for (int i = 0; i < m; i++) {
+        int target;
+        cin >> target;
+        targets.push_back(target);
+    }
+    // 손님이 확인 요청한 부품 번호를 하나씩 확인
+    for (int i = 0; i < m; i++) {
+        // 해당 부품이 존재하는지 확인
+        if (arr[targets[i]] == 1) {
+            cout << "yes" << ' ';
+        }
+        else {
+            cout << "no" << ' ';
+        }
+    }
+}
\ No newline at end of file
diff --git a/7/6.java b/7/6.java
new file mode 100644
index 0000000..5c0705d
--- /dev/null
+++ b/7/6.java
@@ -0,0 +1,35 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        // N(가게의 부품 개수)
+        int n = sc.nextInt();
+        int[] arr = new int[1000001];
+        for (int i = 0; i < n; i++) {
+            int x = sc.nextInt();
+            arr[x] = 1;
+        }
+
+        // M(손님이 확인 요청한 부품 개수)
+        int m = sc.nextInt();
+        int[] targets = new int[n];
+        for (int i = 0; i < m; i++) {
+            targets[i] = sc.nextInt();
+        }
+
+        // 손님이 확인 요청한 부품 번호를 하나씩 확인
+        for (int i = 0; i < m; i++) {
+            // 해당 부품이 존재하는지 확인
+            if (arr[targets[i]] == 1) {
+                System.out.print("yes ");
+            }
+            else {
+                System.out.print("no ");
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/7/6.py b/7/6.py
index 1782fdd..38dbc65 100644
--- a/7/6.py
+++ b/7/6.py
@@ -1,6 +1,6 @@
 # N(가게의 부품 개수) 입력
 n = int(input())
-array = [0] * 1000000
+array = [0] * 1000001
 
 # 가게에 있는 전체 부품 번호를 입력 받아서 기록
 for i in input().split():
diff --git a/7/7.cpp b/7/7.cpp
new file mode 100644
index 0000000..ac5a73d
--- /dev/null
+++ b/7/7.cpp
@@ -0,0 +1,34 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// N(가게의 부품 개수)와 M(손님이 확인 요청한 부품 개수)
+int n, m;
+// 가게게 있는 전체 부품 번호를 담을 집합(set) 컨테이너
+set<int> s;
+vector<int> targets;
+
+int main(void) {
+    cin >> n;
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        s.insert(x);
+    }
+    cin >> m;
+    for (int i = 0; i < m; i++) {
+        int target;
+        cin >> target;
+        targets.push_back(target);
+    }
+    // 손님이 확인 요청한 부품 번호를 하나씩 확인
+    for (int i = 0; i < m; i++) {
+        // 해당 부품이 존재하는지 확인
+        if (s.find(targets[i]) != s.end()) {
+            cout << "yes" << ' ';
+        }
+        else {
+            cout << "no" << ' ';
+        }
+    }
+}
\ No newline at end of file
diff --git a/7/7.java b/7/7.java
new file mode 100644
index 0000000..70c4293
--- /dev/null
+++ b/7/7.java
@@ -0,0 +1,36 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        // N(가게의 부품 개수)
+        int n = sc.nextInt();
+        // 집합(Set) 정보를 처리하기 위한 HashSet 라이브러리
+        HashSet<Integer> s = new HashSet<>();
+        for (int i = 0; i < n; i++) {
+            int x = sc.nextInt();
+            s.add(x);
+        }
+
+        // M(손님이 확인 요청한 부품 개수)
+        int m = sc.nextInt();
+        int[] targets = new int[n];
+        for (int i = 0; i < m; i++) {
+            targets[i] = sc.nextInt();
+        }
+
+        // 손님이 확인 요청한 부품 번호를 하나씩 확인
+        for (int i = 0; i < m; i++) {
+            // 해당 부품이 존재하는지 확인
+            if (s.contains(targets[i])) {
+                System.out.print("yes ");
+            }
+            else {
+                System.out.print("no ");
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/7/8.cpp b/7/8.cpp
new file mode 100644
index 0000000..8171ce0
--- /dev/null
+++ b/7/8.cpp
@@ -0,0 +1,38 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 떡의 개수(N)와 요청한 떡의 길이(M)
+int n, m;
+// 각 떡의 개별 높이 정보 
+vector<int> arr;
+
+int main(void) {
+    cin >> n >> m;
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+    // 이진 탐색을 위한 시작점과 끝점 설정
+    int start = 0;
+    int end = 1e9;
+    // 이진 탐색 수행 (반복적) 
+    int result = 0; 
+    while (start <= end) {
+        long long int total = 0;
+        int mid = (start + end) / 2;
+        for (int i = 0; i < n; i++) {
+            // 잘랐을 때의 떡의 양 계산
+            if (arr[i] > mid) total += arr[i] - mid; 
+        }
+        if (total < m) { // 떡의 양이 부족한 경우 더 많이 자르기(왼쪽 부분 탐색)
+            end = mid - 1;
+        }
+        else { // 떡의 양이 충분한 경우 덜 자르기(오른쪽 부분 탐색)
+            result = mid; // 최대한 덜 잘랐을 때가 정답이므로, 여기에서 result에 기록 
+            start = mid + 1;
+        }
+    }
+    cout << result << '\n';
+}
diff --git a/7/8.java b/7/8.java
new file mode 100644
index 0000000..2417e77
--- /dev/null
+++ b/7/8.java
@@ -0,0 +1,42 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+        
+        // 떡의 개수(N)와 요청한 떡의 길이(M)
+        int n = sc.nextInt();
+        int m = sc.nextInt();
+
+        // 각 떡의 개별 높이 정보 
+        int[] arr = new int[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+
+        // 이진 탐색을 위한 시작점과 끝점 설정
+        int start = 0;
+        int end = (int) 1e9;
+        // 이진 탐색 수행 (반복적)
+        int result = 0; 
+        while (start <= end) {
+            long total = 0;
+            int mid = (start + end) / 2;
+            for (int i = 0; i < n; i++) {
+                // 잘랐을 때의 떡의 양 계산
+                if (arr[i] > mid) total += arr[i] - mid; 
+            }
+            if (total < m) { // 떡의 양이 부족한 경우 더 많이 자르기(왼쪽 부분 탐색)
+                end = mid - 1;
+            }
+            else { // 떡의 양이 충분한 경우 덜 자르기(오른쪽 부분 탐색)
+                result = mid; // 최대한 덜 잘랐을 때가 정답이므로, 여기에서 result에 기록 
+                start = mid + 1;
+            }
+        }
+
+        System.out.println(result);
+    }
+
+}
\ No newline at end of file
diff --git a/7/8.py b/7/8.py
index 5a334c5..4f15658 100644
--- a/7/8.py
+++ b/7/8.py
@@ -12,10 +12,10 @@
 while(start <= end):
     total = 0
     mid = (start + end) // 2
-    for i in array:
+    for x in array:
         # 잘랐을 때의 떡볶이 양 계산
-        if i > mid:
-            total += i - mid
+        if x > mid:
+            total += x - mid
     # 떡볶이 양이 부족한 경우 더 많이 자르기 (오른쪽 부분 탐색)
     if total < m:
         end = mid - 1
diff --git a/8/1.cpp b/8/1.cpp
new file mode 100644
index 0000000..0aedb9d
--- /dev/null
+++ b/8/1.cpp
@@ -0,0 +1,15 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 피보나치 함수(Fibonacci Function)을 재귀함수로 구현
+int fibo(int x) {
+    if (x == 1 || x == 2) {
+        return 1;
+    }
+    return fibo(x - 1) + fibo(x - 2);
+}
+
+int main(void) {
+    cout << fibo(4) << '\n';
+}
\ No newline at end of file
diff --git a/8/1.java b/8/1.java
new file mode 100644
index 0000000..dbe38b1
--- /dev/null
+++ b/8/1.java
@@ -0,0 +1,17 @@
+import java.util.*;
+
+public class Main {
+
+    // 피보나치 함수(Fibonacci Function)을 재귀함수로 구현
+    public static int fibo(int x) {
+        if (x == 1 || x == 2) {
+            return 1;
+        }
+        return fibo(x - 1) + fibo(x - 2);
+    }
+
+    public static void main(String[] args) {
+        System.out.println(fibo(4));
+    }
+
+}
\ No newline at end of file
diff --git a/8/2.cpp b/8/2.cpp
new file mode 100644
index 0000000..b7bb9fc
--- /dev/null
+++ b/8/2.cpp
@@ -0,0 +1,25 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 한 번 계산된 결과를 메모이제이션(Memoization)하기 위한 배열 초기화
+long long d[100];
+
+// 피보나치 함수(Fibonacci Function)를 재귀함수로 구현 (탑다운 다이나믹 프로그래밍)
+long long fibo(int x) {
+    // 종료 조건(1 혹은 2일 때 1을 반환)
+    if (x == 1 || x == 2) {
+        return 1;
+    }
+    // 이미 계산한 적 있는 문제라면 그대로 반환
+    if (d[x] != 0) {
+        return d[x];
+    }
+    // 아직 계산하지 않은 문제라면 점화식에 따라서 피보나치 결과 반환
+    d[x] = fibo(x - 1) + fibo(x - 2);
+    return d[x];
+}
+
+int main(void) {
+    cout << fibo(50) << '\n';
+}
diff --git a/8/2.java b/8/2.java
new file mode 100644
index 0000000..295e6d3
--- /dev/null
+++ b/8/2.java
@@ -0,0 +1,26 @@
+import java.util.*;
+
+public class Main {
+
+    // 한 번 계산된 결과를 메모이제이션(Memoization)하기 위한 배열 초기화
+    public static long[] d = new long[100];
+
+    // 피보나치 함수(Fibonacci Function)를 재귀함수로 구현 (탑다운 다이나믹 프로그래밍)
+    public static long fibo(int x) {
+        // 종료 조건(1 혹은 2일 때 1을 반환)
+        if (x == 1 || x == 2) {
+            return 1;
+        }
+        // 이미 계산한 적 있는 문제라면 그대로 반환
+        if (d[x] != 0) {
+            return d[x];
+        }
+        // 아직 계산하지 않은 문제라면 점화식에 따라서 피보나치 결과 반환
+        d[x] = fibo(x - 1) + fibo(x - 2);
+        return d[x];
+    }
+
+    public static void main(String[] args) {
+        System.out.println(fibo(50));
+    }
+}
\ No newline at end of file
diff --git a/8/3.cpp b/8/3.cpp
new file mode 100644
index 0000000..da71948
--- /dev/null
+++ b/8/3.cpp
@@ -0,0 +1,21 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+long long d[100];
+
+long long fibo(int x) {
+    cout << "f(" << x << ") ";
+    if (x == 1 || x == 2) {
+        return 1;
+    }
+    if (d[x] != 0) {
+        return d[x];
+    }
+    d[x] = fibo(x - 1) + fibo(x - 2);
+    return d[x];
+}
+
+int main(void) {
+    fibo(6);
+}
\ No newline at end of file
diff --git a/8/3.java b/8/3.java
new file mode 100644
index 0000000..3521ae7
--- /dev/null
+++ b/8/3.java
@@ -0,0 +1,24 @@
+import java.util.*;
+
+public class Main {
+
+    public static long[] d = new long[100];
+
+    public static long fibo(int x) {
+        System.out.print("f(" + x + ") ");
+        if (x == 1 || x == 2) {
+            return 1;
+        }
+        // 이미 계산한 적 있는 문제라면 그대로 반환
+        if (d[x] != 0) {
+            return d[x];
+        }
+        // 아직 계산하지 않은 문제라면 점화식에 따라서 피보나치 결과 반환
+        d[x] = fibo(x - 1) + fibo(x - 2);
+        return d[x];
+    }
+
+    public static void main(String[] args) {
+        fibo(6);
+    }
+}
\ No newline at end of file
diff --git a/8/3.py b/8/3.py
index 0402a3e..b50b604 100644
--- a/8/3.py
+++ b/8/3.py
@@ -1,13 +1,12 @@
-# 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화
-d = [0] * 100
-
-# 첫 번째 피보나치 수와 두 번째 피보나치 수는 1
-d[1] = 1
-d[2] = 1
-n = 99
-
-# 피보나치 함수(Fibonacci Function) 반복문으로 구현 (보텀업 다이나믹 프로그래밍)
-for i in range(3, n + 1):
-    d[i] = d[i - 1] + d[i - 2]
-
-print(d[n])
+d = [0] * 100
+
+def fibo(x):
+    print('f(' + str(x) + ')', end=' ')
+    if x == 1 or x == 2:
+        return 1
+    if d[x] != 0:
+        return d[x]
+    d[x] = fibo(x - 1) + fibo(x - 2)
+    return d[x]
+
+fibo(6)
diff --git a/8/4.cpp b/8/4.cpp
new file mode 100644
index 0000000..8e43205
--- /dev/null
+++ b/8/4.cpp
@@ -0,0 +1,19 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화
+long long d[100];
+
+int main(void) {
+    // 첫 번째 피보나치 수와 두 번째 피보나치 수는 1
+    d[1] = 1;
+    d[2] = 1;
+    int n = 50; // 50번째 피보나치 수를 계산
+
+    // 피보나치 함수(Fibonacci Function) 반복문으로 구현(보텀업 다이나믹 프로그래밍)
+    for (int i = 3; i <= n; i++) {
+        d[i] = d[i - 1] + d[i - 2];
+    }
+    cout << d[n] << '\n';
+}
diff --git a/8/4.java b/8/4.java
new file mode 100644
index 0000000..d19abf8
--- /dev/null
+++ b/8/4.java
@@ -0,0 +1,19 @@
+import java.util.*;
+
+public class Main {
+
+    public static long[] d = new long[100];
+
+    public static void main(String[] args) {
+        // 첫 번째 피보나치 수와 두 번째 피보나치 수는 1
+        d[1] = 1;
+        d[2] = 1;
+        int n = 50; // 50번째 피보나치 수를 계산
+
+        // 피보나치 함수(Fibonacci Function) 반복문으로 구현(보텀업 다이나믹 프로그래밍)
+        for (int i = 3; i <= n; i++) {
+            d[i] = d[i - 1] + d[i - 2];
+        }
+        System.out.println(d[n]);
+    }
+}
\ No newline at end of file
diff --git a/8/4.py b/8/4.py
index 92031fc..cd51f38 100644
--- a/8/4.py
+++ b/8/4.py
@@ -1,21 +1,13 @@
-# 정수 X를 입력 받기
-x = int(input())
-
 # 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화
-d = [0] * 1000001
+d = [0] * 100
+
+# 첫 번째 피보나치 수와 두 번째 피보나치 수는 1
+d[1] = 1
+d[2] = 1
+n = 99
 
-# 다이나믹 프로그래밍(Dynamic Programming) 진행 (보텀업)
-for i in range(2, x + 1):
-    # 현재의 수에서 1을 빼는 경우
-    d[i] = d[i - 1] + 1
-    # 현재의 수가 2로 나누어 떨어지는 경우
-    if i % 2 == 0:
-        d[i] = min(d[i], d[i // 2] + 1)
-    # 현재의 수가 3으로 나누어 떨어지는 경우
-    if i % 3 == 0:
-        d[i] = min(d[i], d[i // 3] + 1)
-    # 현재의 수가 5로 나누어 떨어지는 경우
-    if i % 5 == 0:
-        d[i] = min(d[i], d[i // 5] + 1)
+# 피보나치 함수(Fibonacci Function) 반복문으로 구현(보텀업 다이나믹 프로그래밍)
+for i in range(3, n + 1):
+    d[i] = d[i - 1] + d[i - 2]
 
-print(d[x])
+print(d[n])
diff --git a/8/5.cpp b/8/5.cpp
new file mode 100644
index 0000000..4ef162b
--- /dev/null
+++ b/8/5.cpp
@@ -0,0 +1,26 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 
+int d[30001];
+int x;
+
+int main(void) {
+    cin >> x;
+    // 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+    for (int i = 2; i <= x; i++) {
+        // 현재의 수에서 1을 빼는 경우
+        d[i] = d[i - 1] + 1;
+        // 현재의 수가 2로 나누어 떨어지는 경우
+        if (i % 2 == 0)
+            d[i] = min(d[i], d[i / 2] + 1);
+        // 현재의 수가 3으로 나누어 떨어지는 경우
+        if (i % 3 == 0)
+            d[i] = min(d[i], d[i / 3] + 1);
+        // 현재의 수가 5로 나누어 떨어지는 경우
+        if (i % 5 == 0)
+            d[i] = min(d[i], d[i / 5] + 1);
+    }
+    cout << d[x] << '\n';
+}
\ No newline at end of file
diff --git a/8/5.java b/8/5.java
new file mode 100644
index 0000000..2e6f308
--- /dev/null
+++ b/8/5.java
@@ -0,0 +1,30 @@
+import java.util.*;
+
+public class Main {
+
+    // 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 
+    public static int[] d = new int[30001];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        int x = sc.nextInt();
+
+        // 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+        for (int i = 2; i <= x; i++) {
+            // 현재의 수에서 1을 빼는 경우
+            d[i] = d[i - 1] + 1;
+            // 현재의 수가 2로 나누어 떨어지는 경우
+            if (i % 2 == 0)
+                d[i] = Math.min(d[i], d[i / 2] + 1);
+            // 현재의 수가 3으로 나누어 떨어지는 경우
+            if (i % 3 == 0)
+                d[i] = Math.min(d[i], d[i / 3] + 1);
+            // 현재의 수가 5로 나누어 떨어지는 경우
+            if (i % 5 == 0)
+                d[i] = Math.min(d[i], d[i / 5] + 1);
+        }
+
+        System.out.println(d[x]);
+    }
+}
\ No newline at end of file
diff --git a/8/5.py b/8/5.py
index 941e1bc..00ea183 100644
--- a/8/5.py
+++ b/8/5.py
@@ -1,16 +1,21 @@
-# 정수 N을 입력 받기
-n = int(input())
-# 모든 식량 정보 입력 받기
-array = list(map(int, input().split()))
+# 정수 X를 입력 받기
+x = int(input())
 
 # 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화
-d = [0] * 100
+d = [0] * 1000001
 
-# 다이나믹 프로그래밍(Dynamic Programming) 진행 (보텀업)
-d[0] = array[0]
-d[1] = max(array[0], array[1]) 
-for i in range(2, n):
-    d[i] = max(d[i - 1], d[i - 2] + array[i])
+# 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+for i in range(2, x + 1):
+    # 현재의 수에서 1을 빼는 경우
+    d[i] = d[i - 1] + 1
+    # 현재의 수가 2로 나누어 떨어지는 경우
+    if i % 2 == 0:
+        d[i] = min(d[i], d[i // 2] + 1)
+    # 현재의 수가 3으로 나누어 떨어지는 경우
+    if i % 3 == 0:
+        d[i] = min(d[i], d[i // 3] + 1)
+    # 현재의 수가 5로 나누어 떨어지는 경우
+    if i % 5 == 0:
+        d[i] = min(d[i], d[i // 5] + 1)
 
-# 계산된 결과 출력
-print(d[n - 1])
+print(d[x])
diff --git a/8/6.cpp b/8/6.cpp
new file mode 100644
index 0000000..aba7f5f
--- /dev/null
+++ b/8/6.cpp
@@ -0,0 +1,29 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화
+int d[100];
+int n;
+vector<int> arr;
+
+int main(void) {
+    // 정수 N을 입력받기
+    cin >> n;
+    // 모든 식량 정보 입력받기
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+
+    // 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+    d[0] = arr[0];
+    d[1] = max(arr[0], arr[1]);
+    for (int i = 2; i < n; i++) {
+        d[i] = max(d[i - 1], d[i - 2] + arr[i]);
+    }
+
+    // 계산된 결과 출력
+    cout << d[n - 1] << '\n';
+}
\ No newline at end of file
diff --git a/8/6.java b/8/6.java
new file mode 100644
index 0000000..029375d
--- /dev/null
+++ b/8/6.java
@@ -0,0 +1,30 @@
+import java.util.*;
+
+public class Main {
+
+    // 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 
+    public static int[] d = new int[100];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // 정수 N을 입력받기
+        int n = sc.nextInt();
+
+        // 모든 식량 정보 입력받기
+        int[] arr = new int[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+        
+        // 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+        d[0] = arr[0];
+        d[1] = Math.max(arr[0], arr[1]);
+        for (int i = 2; i < n; i++) {
+            d[i] = Math.max(d[i - 1], d[i - 2] + arr[i]);
+        }
+
+        // 계산된 결과 출력
+        System.out.println(d[n - 1]);
+    }
+}
\ No newline at end of file
diff --git a/8/6.py b/8/6.py
index 0cc661f..941e1bc 100644
--- a/8/6.py
+++ b/8/6.py
@@ -1,14 +1,16 @@
 # 정수 N을 입력 받기
 n = int(input())
+# 모든 식량 정보 입력 받기
+array = list(map(int, input().split()))
 
 # 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화
-d = [0] * 1000001
+d = [0] * 100
 
 # 다이나믹 프로그래밍(Dynamic Programming) 진행 (보텀업)
-d[1] = 1
-d[2] = 3
-for i in range(3, n + 1):
-    d[i] = (d[i - 1] + 2 * d[i - 2]) % 796796
+d[0] = array[0]
+d[1] = max(array[0], array[1]) 
+for i in range(2, n):
+    d[i] = max(d[i - 1], d[i - 2] + array[i])
 
 # 계산된 결과 출력
-print(d[n])
+print(d[n - 1])
diff --git a/8/7.cpp b/8/7.cpp
new file mode 100644
index 0000000..fc76c01
--- /dev/null
+++ b/8/7.cpp
@@ -0,0 +1,22 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+// 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화
+int d[1001];
+int n;
+
+int main(void) {
+    // 정수 N을 입력받기
+    cin >> n;
+
+    // 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+    d[1] = 1;
+    d[2] = 3;
+    for (int i = 3; i <= n; i++) {
+        d[i] = (d[i - 1] + 2 * d[i - 2]) % 796796;
+    }
+
+    // 계산된 결과 출력
+    cout << d[n] << '\n';
+}
\ No newline at end of file
diff --git a/8/7.java b/8/7.java
new file mode 100644
index 0000000..7e29bed
--- /dev/null
+++ b/8/7.java
@@ -0,0 +1,24 @@
+import java.util.*;
+
+public class Main {
+
+    // 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 
+    public static int[] d = new int[1001];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // 정수 N을 입력받기
+        int n = sc.nextInt();
+
+        // 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+        d[1] = 1;
+        d[2] = 3;
+        for (int i = 3; i <= n; i++) {
+            d[i] = (d[i - 1] + 2 * d[i - 2]) % 796796;
+        }
+
+        // 계산된 결과 출력
+        System.out.println(d[n]);
+    }
+}
\ No newline at end of file
diff --git a/8/7.py b/8/7.py
index cd2ef37..0c69f04 100644
--- a/8/7.py
+++ b/8/7.py
@@ -1,22 +1,14 @@
-# 정수 N, M을 입력 받기
-n, m = map(int, input().split())
-# N개의 화폐 단위 정보를 입력 받기
-array = []
-for i in range(n):
-    array.append(int(input()))
+# 정수 N을 입력 받기
+n = int(input())
 
-# 한 번 계산된 결과를 저장하기 위한 DP 테이블 초기화
-d = [10001] * (m + 1)
+# 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화
+d = [0] * 1001
 
 # 다이나믹 프로그래밍(Dynamic Programming) 진행 (보텀업)
-d[0] = 0
-for i in range(n):
-    for j in range(array[i], m + 1):
-        if d[j - array[i]] != 10001: # (i - k) 원을 만드는 방법이 존재하는 경우
-            d[j] = min(d[j], d[j - array[i]] + 1)
+d[1] = 1
+d[2] = 3
+for i in range(3, n + 1):
+    d[i] = (d[i - 1] + 2 * d[i - 2]) % 796796
 
 # 계산된 결과 출력
-if d[m] == 10001: # 최종적으로 m 원을 만드는 방법이 없는 경우
-    print(-1)
-else:
-    print(d[m])
+print(d[n])
diff --git a/8/8.cpp b/8/8.cpp
new file mode 100644
index 0000000..09b4ec1
--- /dev/null
+++ b/8/8.cpp
@@ -0,0 +1,40 @@
+#include <bits/stdc++.h>
+
+using namespace std;
+
+int n, m;
+vector<int> arr;
+
+int main(void) {
+    // 정수 N, M을 입력받기
+    cin >> n >> m;
+    
+    // N개의 화폐 단위 정보를 입력 받기
+    for (int i = 0; i < n; i++) {
+        int x;
+        cin >> x;
+        arr.push_back(x);
+    }
+
+    // 한 번 계산된 결과를 저장하기 위한 DP 테이블 초기화
+    vector<int> d(m + 1, 10001);
+
+    // 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+    d[0] = 0;
+    for (int i = 0; i < n; i++) {
+        for (int j = arr[i]; j <= m; j++) {
+            // (i - k)원을 만드는 방법이 존재하는 경우
+            if (d[j - arr[i]] != 10001) {
+                d[j] = min(d[j], d[j - arr[i]] + 1);
+            }
+        }
+    }
+
+    // 계산된 결과 출력
+    if (d[m] == 10001) { // 최종적으로 M원을 만드는 방법이 없는 경우
+        cout << -1 << '\n';
+    }
+    else {
+        cout << d[m] << '\n';
+    }
+}
diff --git a/8/8.java b/8/8.java
new file mode 100644
index 0000000..2ddd4fa
--- /dev/null
+++ b/8/8.java
@@ -0,0 +1,41 @@
+import java.util.*;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        // 정수 N, M을 입력받기
+        int n = sc.nextInt();
+        int m = sc.nextInt();
+
+        // N개의 화폐 단위 정보를 입력 받기
+        int[] arr = new int[n];
+        for (int i = 0; i < n; i++) {
+            arr[i] = sc.nextInt();
+        }
+
+        // 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 
+        int[] d = new int[m + 1];
+        Arrays.fill(d, 10001);
+
+        // 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+        d[0] = 0;
+        for (int i = 0; i < n; i++) {
+            for (int j = arr[i]; j <= m; j++) {
+                // (i - k)원을 만드는 방법이 존재하는 경우
+                if (d[j - arr[i]] != 10001) {
+                    d[j] = Math.min(d[j], d[j - arr[i]] + 1);
+                }
+            }
+        }
+
+        // 계산된 결과 출력
+        if (d[m] == 10001) { // 최종적으로 M원을 만드는 방법이 없는 경우
+            System.out.println(-1);
+        }
+        else {
+            System.out.println(d[m]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/8/8.py b/8/8.py
new file mode 100644
index 0000000..4a10b9b
--- /dev/null
+++ b/8/8.py
@@ -0,0 +1,22 @@
+# 정수 N, M을 입력 받기
+n, m = map(int, input().split())
+# N개의 화폐 단위 정보를 입력 받기
+array = []
+for i in range(n):
+    array.append(int(input()))
+
+# 한 번 계산된 결과를 저장하기 위한 DP 테이블 초기화
+d = [10001] * (m + 1)
+
+# 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
+d[0] = 0
+for i in range(n):
+    for j in range(array[i], m + 1):
+        if d[j - array[i]] != 10001: # (i - k)원을 만드는 방법이 존재하는 경우
+            d[j] = min(d[j], d[j - array[i]] + 1)
+
+# 계산된 결과 출력
+if d[m] == 10001: # 최종적으로 M원을 만드는 방법이 없는 경우
+    print(-1)
+else:
+    print(d[m])
diff --git a/9/1.cpp b/9/1.cpp
new file mode 100644
index 0000000..b254ce8
--- /dev/null
+++ b/9/1.cpp
@@ -0,0 +1,80 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+// 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start)
+// 노드의 개수는 최대 100,000개라고 가정
+int n, m, start;
+// 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열
+vector<pair<int, int> > graph[100001];
+// 방문한 적이 있는지 체크하는 목적의 배열 만들기
+bool visited[100001];
+// 최단 거리 테이블 만들기
+int d[100001];
+
+// 방문하지 않은 노드 중에서, 가장 최단 거리가 짧은 노드의 번호를 반환
+int getSmallestNode() {
+    int min_value = INF;
+    int index = 0; // 가장 최단 거리가 짧은 노드(인덱스)
+    for (int i = 1; i <= n; i++) {
+        if (d[i] < min_value && !visited[i]) {
+            min_value = d[i];
+            index = i;
+        }
+    }
+    return index;
+}
+
+void dijkstra(int start) {
+    // 시작 노드에 대해서 초기화
+    d[start] = 0;
+    visited[start] = true;
+    for (int j = 0; j < graph[start].size(); j++) {
+        d[graph[start][j].first] = graph[start][j].second;
+    }
+    // 시작 노드를 제외한 전체 n - 1개의 노드에 대해 반복
+    for (int i = 0; i < n - 1; i++) {
+        // 현재 최단 거리가 가장 짧은 노드를 꺼내서, 방문 처리
+        int now = getSmallestNode();
+        visited[now] = true;
+        // 현재 노드와 연결된 다른 노드를 확인
+        for (int j = 0; j < graph[now].size(); j++) {
+            int cost = d[now] + graph[now][j].second;
+            // 현재 노드를 거쳐서 다른 노드로 이동하는 거리가 더 짧은 경우
+            if (cost < d[graph[now][j].first]) {
+                d[graph[now][j].first] = cost;
+            }
+        }
+    }
+}
+
+int main(void) {
+    cin >> n >> m >> start;
+
+    // 모든 간선 정보를 입력받기
+    for (int i = 0; i < m; i++) {
+        int a, b, c;
+        cin >> a >> b >> c;
+        // a번 노드에서 b번 노드로 가는 비용이 c라는 의미
+        graph[a].push_back({b, c});
+    }
+
+    // 최단 거리 테이블을 모두 무한으로 초기화
+    fill_n(d, 100001, INF);
+    
+    // 다익스트라 알고리즘을 수행
+    dijkstra(start);
+
+    // 모든 노드로 가기 위한 최단 거리를 출력
+    for (int i = 1; i <= n; i++) {
+        // 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
+        if (d[i] == INF) {
+            cout << "INFINITY" << '\n';
+        }
+        // 도달할 수 있는 경우 거리를 출력
+        else {
+            cout << d[i] << '\n';
+        }
+    }
+}
\ No newline at end of file
diff --git a/9/1.java b/9/1.java
new file mode 100644
index 0000000..cb9b4ec
--- /dev/null
+++ b/9/1.java
@@ -0,0 +1,110 @@
+import java.util.*;
+
+class Node {
+
+    private int index;
+    private int distance;
+
+    public Node(int index, int distance) {
+        this.index = index;
+        this.distance = distance;
+    }
+
+    public int getIndex() {
+        return this.index;
+    }
+
+    public int getDistance() {
+        return this.distance;
+    }
+}
+
+public class Main {
+
+    public static final int INF = (int) 1e9; // 무한을 의미하는 값으로 10억을 설정
+    // 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start)
+    // 노드의 개수는 최대 100,000개라고 가정
+    public static int n, m, start;
+    // 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열
+    public static ArrayList<ArrayList<Node>> graph = new ArrayList<ArrayList<Node>>();
+    // 방문한 적이 있는지 체크하는 목적의 배열 만들기
+    public static boolean[] visited = new boolean[100001];
+    // 최단 거리 테이블 만들기
+    public static int[] d = new int[100001];
+
+    // 방문하지 않은 노드 중에서, 가장 최단 거리가 짧은 노드의 번호를 반환
+    public static int getSmallestNode() {
+        int min_value = INF;
+        int index = 0; // 가장 최단 거리가 짧은 노드(인덱스)
+        for (int i = 1; i <= n; i++) {
+            if (d[i] < min_value && !visited[i]) {
+                min_value = d[i];
+                index = i;
+            }
+        }
+        return index;
+    }
+
+    public static void dijkstra(int start) {
+        // 시작 노드에 대해서 초기화
+        d[start] = 0;
+        visited[start] = true;
+        for (int j = 0; j < graph.get(start).size(); j++) {
+            d[graph.get(start).get(j).getIndex()] = graph.get(start).get(j).getDistance();
+        }
+        // 시작 노드를 제외한 전체 n - 1개의 노드에 대해 반복
+        for (int i = 0; i < n - 1; i++) {
+            // 현재 최단 거리가 가장 짧은 노드를 꺼내서, 방문 처리
+            int now = getSmallestNode();
+            visited[now] = true;
+            // 현재 노드와 연결된 다른 노드를 확인
+            for (int j = 0; j < graph.get(now).size(); j++) {
+                int cost = d[now] + graph.get(now).get(j).getDistance();
+                // 현재 노드를 거쳐서 다른 노드로 이동하는 거리가 더 짧은 경우
+                if (cost < d[graph.get(now).get(j).getIndex()]) {
+                    d[graph.get(now).get(j).getIndex()] = cost;
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+        start = sc.nextInt();
+
+        // 그래프 초기화
+        for (int i = 0; i <= n; i++) {
+            graph.add(new ArrayList<Node>());
+        }
+
+        // 모든 간선 정보를 입력받기
+        for (int i = 0; i < m; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            int c = sc.nextInt();
+            // a번 노드에서 b번 노드로 가는 비용이 c라는 의미
+            graph.get(a).add(new Node(b, c));
+        }
+
+        // 최단 거리 테이블을 모두 무한으로 초기화
+        Arrays.fill(d, INF);
+        
+        // 다익스트라 알고리즘을 수행
+        dijkstra(start);
+
+        // 모든 노드로 가기 위한 최단 거리를 출력
+        for (int i = 1; i <= n; i++) {
+            // 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
+            if (d[i] == INF) {
+                System.out.println("INFINITY");
+            }
+            // 도달할 수 있는 경우 거리를 출력
+            else {
+                System.out.println(d[i]);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/9/1.py b/9/1.py
index 9190612..ad5b9c3 100644
--- a/9/1.py
+++ b/9/1.py
@@ -1,28 +1,28 @@
 import sys
 input = sys.stdin.readline
-INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정합니다.
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
 
-# 노드의 개수, 간선의 개수를 입력 받습니다.
+# 노드의 개수, 간선의 개수를 입력받기
 n, m = map(int, input().split())
-# 시작 노드 번호를 입력 받습니다.
+# 시작 노드 번호를 입력받기
 start = int(input())
-# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만듭니다.
+# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
 graph = [[] for i in range(n + 1)]
-# 방문한 적이 있는지 체크하는 목적의 리스트를 만듭니다.
+# 방문한 적이 있는지 체크하는 목적의 리스트를 만들기
 visited = [False] * (n + 1)
-# 최단 거리 테이블을 모두 무한으로 초기화합니다.
+# 최단 거리 테이블을 모두 무한으로 초기화
 distance = [INF] * (n + 1)
 
-# 모든 간선 정보를 입력 받습니다.
+# 모든 간선 정보를 입력받기
 for _ in range(m):
     a, b, c = map(int, input().split())
-    # a번 노드에서 b번 노드로 가는 비용이 c라는 의미입니다.
+    # a번 노드에서 b번 노드로 가는 비용이 c라는 의미
     graph[a].append((b, c))
 
-# 방문하지 않은 노드 중에서, 가장 최단 거리가 짧은 노드의 번호를 반환합니다.
+# 방문하지 않은 노드 중에서, 가장 최단 거리가 짧은 노드의 번호를 반환
 def get_smallest_node():
     min_value = INF
-    index = 0 # 가장 최단 거리가 짧은 노드 (인덱스)
+    index = 0 # 가장 최단 거리가 짧은 노드(인덱스)
     for i in range(1, n + 1):
         if distance[i] < min_value and not visited[i]:
             min_value = distance[i]
@@ -30,31 +30,31 @@ def get_smallest_node():
     return index
 
 def dijkstra(start):
-    # 시작 노드에 대해서 초기화합니다.
+    # 시작 노드에 대해서 초기화
     distance[start] = 0
     visited[start] = True
     for j in graph[start]:
         distance[j[0]] = j[1]
-    # 시작 노드를 제외한 전체 n - 1개의 노드에 대해 반복합니다.
+    # 시작 노드를 제외한 전체 n - 1개의 노드에 대해 반복
     for i in range(n - 1):
-        # 현재 최단 거리가 가장 짧은 노드를 꺼내서, 방문 처리합니다.
+        # 현재 최단 거리가 가장 짧은 노드를 꺼내서, 방문 처리
         now = get_smallest_node()
         visited[now] = True
-        # 현재 노드와 연결된 다른 노드를 확인합니다.
+        # 현재 노드와 연결된 다른 노드를 확인
         for j in graph[now]:
             cost = distance[now] + j[1]
             # 현재 노드를 거쳐서 다른 노드로 이동하는 거리가 더 짧은 경우
             if cost < distance[j[0]]:
                 distance[j[0]] = cost
 
-# 다익스트라 알고리즘을 수행합니다.
+# 다익스트라 알고리즘을 수행
 dijkstra(start)
 
-# 모든 노드로 가기 위한 최단 거리를 출력합니다.
+# 모든 노드로 가기 위한 최단 거리를 출력
 for i in range(1, n + 1):
-    # 도달할 수 없는 경우, 무한(INFINITY)이라고 출력합니다.
+    # 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
     if distance[i] == INF:
         print("INFINITY")
-    # 도달할 수 있는 경우 거리를 출력합니다.
+    # 도달할 수 있는 경우 거리를 출력
     else:
         print(distance[i])
diff --git a/9/2.cpp b/9/2.cpp
new file mode 100644
index 0000000..b19dd7c
--- /dev/null
+++ b/9/2.cpp
@@ -0,0 +1,66 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+// 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start)
+// 노드의 개수는 최대 100,000개라고 가정
+int n, m, start;
+// 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열
+vector<pair<int, int> > graph[100001];
+// 최단 거리 테이블 만들기
+int d[100001];
+
+void dijkstra(int start) {
+    priority_queue<pair<int, int> > pq;
+    // 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+    pq.push({0, start});
+    d[start] = 0;
+    while (!pq.empty()) { // 큐가 비어있지 않다면
+        // 가장 최단 거리가 짧은 노드에 대한 정보 꺼내기
+        int dist = -pq.top().first; // 현재 노드까지의 비용 
+        int now = pq.top().second; // 현재 노드
+        pq.pop();
+        // 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+        if (d[now] < dist) continue;
+        // 현재 노드와 연결된 다른 인접한 노드들을 확인
+        for (int i = 0; i < graph[now].size(); i++) {
+            int cost = dist + graph[now][i].second;
+            // 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+            if (cost < d[graph[now][i].first]) {
+                d[graph[now][i].first] = cost;
+                pq.push(make_pair(-cost, graph[now][i].first));
+            }
+        }
+    }
+}
+
+int main(void) {
+    cin >> n >> m >> start;
+
+    // 모든 간선 정보를 입력받기
+    for (int i = 0; i < m; i++) {
+        int a, b, c;
+        cin >> a >> b >> c;
+        // a번 노드에서 b번 노드로 가는 비용이 c라는 의미
+        graph[a].push_back({b, c});
+    }
+
+    // 최단 거리 테이블을 모두 무한으로 초기화
+    fill(d, d + 100001, INF);
+    
+    // 다익스트라 알고리즘을 수행
+    dijkstra(start);
+
+    // 모든 노드로 가기 위한 최단 거리를 출력
+    for (int i = 1; i <= n; i++) {
+        // 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
+        if (d[i] == INF) {
+            cout << "INFINITY" << '\n';
+        }
+        // 도달할 수 있는 경우 거리를 출력
+        else {
+            cout << d[i] << '\n';
+        }
+    }
+}
\ No newline at end of file
diff --git a/9/2.java b/9/2.java
new file mode 100644
index 0000000..1f94a2c
--- /dev/null
+++ b/9/2.java
@@ -0,0 +1,105 @@
+import java.util.*;
+
+class Node implements Comparable<Node> {
+
+    private int index;
+    private int distance;
+
+    public Node(int index, int distance) {
+        this.index = index;
+        this.distance = distance;
+    }
+
+    public int getIndex() {
+        return this.index;
+    }
+
+    public int getDistance() {
+        return this.distance;
+    }
+
+    // 거리(비용)가 짧은 것이 높은 우선순위를 가지도록 설정
+    @Override
+    public int compareTo(Node other) {
+        if (this.distance < other.distance) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+
+    public static final int INF = (int) 1e9; // 무한을 의미하는 값으로 10억을 설정
+    // 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start)
+    // 노드의 개수는 최대 100,000개라고 가정
+    public static int n, m, start;
+    // 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열
+    public static ArrayList<ArrayList<Node>> graph = new ArrayList<ArrayList<Node>>();
+    // 최단 거리 테이블 만들기
+    public static int[] d = new int[100001];
+
+    public static void dijkstra(int start) {
+        PriorityQueue<Node> pq = new PriorityQueue<>();
+        // 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+        pq.offer(new Node(start, 0));
+        d[start] = 0;
+        while(!pq.isEmpty()) { // 큐가 비어있지 않다면
+            // 가장 최단 거리가 짧은 노드에 대한 정보 꺼내기
+            Node node = pq.poll();
+            int dist = node.getDistance(); // 현재 노드까지의 비용 
+            int now = node.getIndex(); // 현재 노드
+            // 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+            if (d[now] < dist) continue;
+            // 현재 노드와 연결된 다른 인접한 노드들을 확인
+            for (int i = 0; i < graph.get(now).size(); i++) {
+                int cost = d[now] + graph.get(now).get(i).getDistance();
+                // 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+                if (cost < d[graph.get(now).get(i).getIndex()]) {
+                    d[graph.get(now).get(i).getIndex()] = cost;
+                    pq.offer(new Node(graph.get(now).get(i).getIndex(), cost));
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+        start = sc.nextInt();
+
+        // 그래프 초기화
+        for (int i = 0; i <= n; i++) {
+            graph.add(new ArrayList<Node>());
+        }
+        
+        // 모든 간선 정보를 입력받기
+        for (int i = 0; i < m; i++) {
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            int c = sc.nextInt();
+            // a번 노드에서 b번 노드로 가는 비용이 c라는 의미
+            graph.get(a).add(new Node(b, c));
+        }
+
+        // 최단 거리 테이블을 모두 무한으로 초기화
+        Arrays.fill(d, INF);
+        
+        // 다익스트라 알고리즘을 수행
+        dijkstra(start);
+
+        // 모든 노드로 가기 위한 최단 거리를 출력
+        for (int i = 1; i <= n; i++) {
+            // 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
+            if (d[i] == INF) {
+                System.out.println("INFINITY");
+            }
+            // 도달할 수 있는 경우 거리를 출력
+            else {
+                System.out.println(d[i]);
+            }
+        }
+    }
+}
diff --git a/9/2.py b/9/2.py
index b0000a0..626a496 100644
--- a/9/2.py
+++ b/9/2.py
@@ -1,35 +1,35 @@
 import heapq
 import sys
 input = sys.stdin.readline
-INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정합니다.
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
 
-# 노드의 개수, 간선의 개수를 입력 받습니다.
+# 노드의 개수, 간선의 개수를 입력받기
 n, m = map(int, input().split())
-# 시작 노드 번호를 입력 받습니다.
+# 시작 노드 번호를 입력받기
 start = int(input())
-# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만듭니다.
+# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
 graph = [[] for i in range(n + 1)]
-# 최단 거리 테이블을 모두 무한으로 초기화합니다.
+# 최단 거리 테이블을 모두 무한으로 초기화
 distance = [INF] * (n + 1)
 
-# 모든 간선 정보를 입력 받습니다.
+# 모든 간선 정보를 입력받기
 for _ in range(m):
     a, b, c = map(int, input().split())
-    # a번 노드에서 b번 노드로 가는 비용이 c라는 의미입니다.
+    # a번 노드에서 b번 노드로 가는 비용이 c라는 의미
     graph[a].append((b, c))
 
 def dijkstra(start):
-   q = []
-   # 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입합니다.
-   heapq.heappush(q, (0, start))
-   distance[start] = 0
-   while q: # 큐가 비어있지 않다면
-        # 가장 최단 거리가 짧은 노드에 대한 정보를 꺼냅니다.
+    q = []
+    # 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+    heapq.heappush(q, (0, start))
+    distance[start] = 0
+    while q: # 큐가 비어있지 않다면
+        # 가장 최단 거리가 짧은 노드에 대한 정보 꺼내기
         dist, now = heapq.heappop(q)
-        # 현재 노드가 이미 처리된 적이 있는 노드라면 무시합니다.
+        # 현재 노드가 이미 처리된 적이 있는 노드라면 무시
         if distance[now] < dist:
             continue
-        # 현재 노드와 연결된 다른 인접한 노드들을 확인합니다.
+        # 현재 노드와 연결된 다른 인접한 노드들을 확인
         for i in graph[now]:
             cost = dist + i[1]
             # 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
@@ -37,14 +37,14 @@ def dijkstra(start):
                 distance[i[0]] = cost
                 heapq.heappush(q, (cost, i[0]))
 
-# 다익스트라 알고리즘을 수행합니다.
+# 다익스트라 알고리즘을 수행
 dijkstra(start)
 
-# 모든 노드로 가기 위한 최단 거리를 출력합니다.
+# 모든 노드로 가기 위한 최단 거리를 출력
 for i in range(1, n + 1):
-    # 도달할 수 없는 경우, 무한(INFINITY)이라고 출력합니다.
+    # 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
     if distance[i] == INF:
         print("INFINITY")
-    # 도달할 수 있는 경우 거리를 출력합니다.
+    # 도달할 수 있는 경우 거리를 출력
     else:
         print(distance[i])
diff --git a/9/3.cpp b/9/3.cpp
new file mode 100644
index 0000000..3be9d33
--- /dev/null
+++ b/9/3.cpp
@@ -0,0 +1,58 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+// 노드의 개수(N), 간선의 개수(M)
+// 노드의 개수는 최대 500개라고 가정
+int n, m;
+// 2차원 배열(그래프 표현)를 만들기
+int graph[501][501];
+
+int main(void) {
+    cin >> n >> m;
+
+    // 최단 거리 테이블을 모두 무한으로 초기화
+    for (int i = 0; i < 501; i++) {
+        fill(graph[i], graph[i] + 501, INF);
+    }
+
+    // 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+    for (int a = 1; a <= n; a++) {
+        for (int b = 1; b <= n; b++) {
+            if (a == b) graph[a][b] = 0;
+        }
+    }
+
+    // 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
+    for (int i = 0; i < m; i++) {
+        // A에서 B로 가는 비용은 C라고 설정
+        int a, b, c;
+        cin >> a >> b >> c;
+        graph[a][b] = c;
+    }
+    
+    // 점화식에 따라 플로이드 워셜 알고리즘을 수행
+    for (int k = 1; k <= n; k++) {
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b]);
+            }
+        }
+    }
+
+    // 수행된 결과를 출력
+    for (int a = 1; a <= n; a++) {
+        for (int b = 1; b <= n; b++) {
+            // 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
+            if (graph[a][b] == INF) {
+                cout << "INFINITY" << ' ';
+            }
+            // 도달할 수 있는 경우 거리를 출력
+            else {
+                cout << graph[a][b] << ' ';
+            }
+        }
+        cout << '\n';
+    }
+}
\ No newline at end of file
diff --git a/9/3.java b/9/3.java
new file mode 100644
index 0000000..cdb20d2
--- /dev/null
+++ b/9/3.java
@@ -0,0 +1,63 @@
+import java.util.*;
+
+public class Main {
+
+    public static final int INF = (int) 1e9; // 무한을 의미하는 값으로 10억을 설정
+    // 노드의 개수(N), 간선의 개수(M)
+    // 노드의 개수는 최대 500개라고 가정
+    public static int n, m;
+    // 2차원 배열(그래프 표현)를 만들기
+    public static int[][] graph = new int[501][501];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        // 최단 거리 테이블을 모두 무한으로 초기화
+        for (int i = 0; i < 501; i++) {
+            Arrays.fill(graph[i], INF);
+        }
+
+        // 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                if (a == b) graph[a][b] = 0;
+            }
+        }
+
+        // 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
+        for (int i = 0; i < m; i++) {
+            // A에서 B로 가는 비용은 C라고 설정
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            int c = sc.nextInt();
+            graph[a][b] = c;
+        }
+
+        // 점화식에 따라 플로이드 워셜 알고리즘을 수행
+        for (int k = 1; k <= n; k++) {
+            for (int a = 1; a <= n; a++) {
+                for (int b = 1; b <= n; b++) {
+                    graph[a][b] = Math.min(graph[a][b], graph[a][k] + graph[k][b]);
+                }
+            }
+        }
+
+        // 수행된 결과를 출력
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                // 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
+                if (graph[a][b] == INF) {
+                    System.out.print("INFINITY ");
+                }
+                // 도달할 수 있는 경우 거리를 출력
+                else {
+                    System.out.print(graph[a][b] + " ");
+                }
+            }
+            System.out.println();
+        }
+    }
+}
\ No newline at end of file
diff --git a/9/3.py b/9/3.py
index 3c74de4..a92ea2b 100644
--- a/9/3.py
+++ b/9/3.py
@@ -1,36 +1,36 @@
-INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정합니다.
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
 
-# 노드의 개수 및 간선의 개수를 입력 받습니다.
+# 노드의 개수 및 간선의 개수를 입력받기
 n = int(input())
 m = int(input())
-# 2차원 리스트(그래프 표현)를 만들고, 모든 값을 무한으로 초기화합니다.
+# 2차원 리스트(그래프 표현)를 만들고, 모든 값을 무한으로 초기화
 graph = [[INF] * (n + 1) for _ in range(n + 1)]
 
-# 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화합니다.
+# 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
 for a in range(1, n + 1):
     for b in range(1, n + 1):
         if a == b:
             graph[a][b] = 0
 
-# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화합니다.
+# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
 for _ in range(m):
-    # A에서 B로 가는 비용은 C라고 설정합니다.
+    # A에서 B로 가는 비용은 C라고 설정
     a, b, c = map(int, input().split())
     graph[a][b] = c
 
-# 점화식에 따라 플로이드 워셜 알고리즘을 수행합니다.
+# 점화식에 따라 플로이드 워셜 알고리즘을 수행
 for k in range(1, n + 1):
     for a in range(1, n + 1):
         for b in range(1, n + 1):
             graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])
 
-# 수행된 결과를 출력합니다.
+# 수행된 결과를 출력
 for a in range(1, n + 1):
     for b in range(1, n + 1):
-        # 도달할 수 없는 경우, 무한(INFINITY)이라고 출력합니다.
+        # 도달할 수 없는 경우, 무한(INFINITY)이라고 출력
         if graph[a][b] == 1e9:
             print("INFINITY", end=" ")
-        # 도달할 수 있는 경우 거리를 출력합니다.
+        # 도달할 수 있는 경우 거리를 출력
         else:
             print(graph[a][b], end=" ")
     print()
diff --git a/9/4.cpp b/9/4.cpp
new file mode 100644
index 0000000..9e625b4
--- /dev/null
+++ b/9/4.cpp
@@ -0,0 +1,59 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+// 노드의 개수(N), 간선의 개수(M)
+int n, m;
+// 2차원 배열(그래프 표현)를 만들기
+int graph[101][101];
+
+int main(void) {
+    cin >> n >> m;
+
+    // 최단 거리 테이블을 모두 무한으로 초기화
+    for (int i = 0; i < 101; i++) {
+        fill(graph[i], graph[i] + 101, INF);
+    }
+
+    // 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+    for (int a = 1; a <= n; a++) {
+        for (int b = 1; b <= n; b++) {
+            if (a == b) graph[a][b] = 0;
+        }
+    }
+
+    // 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
+    for (int i = 0; i < m; i++) {
+        // A와 B가 서로에게 가는 비용은 1이라고 설정
+        int a, b;
+        cin >> a >> b;
+        graph[a][b] = 1;
+        graph[b][a] = 1;
+    }
+
+    // 거쳐 갈 노드 X와 최종 목적지 노드 K를 입력받기
+    int x, k;
+    cin >> x >> k;
+
+    // 점화식에 따라 플로이드 워셜 알고리즘을 수행
+    for (int k = 1; k <= n; k++) {
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b]);
+            }
+        }
+    }
+
+    // 수행된 결과를 출력
+    int distance = graph[1][k] + graph[k][x];
+
+    // 도달할 수 없는 경우, -1을 출력
+    if (distance >= INF) {
+        cout << "-1" << '\n';
+    }
+    // 도달할 수 있다면, 최단 거리를 출력
+    else {
+        cout << distance << '\n';
+    }
+}
\ No newline at end of file
diff --git a/9/4.java b/9/4.java
new file mode 100644
index 0000000..8c74fa9
--- /dev/null
+++ b/9/4.java
@@ -0,0 +1,62 @@
+import java.util.*;
+
+public class Main {
+
+    public static final int INF = (int) 1e9; // 무한을 의미하는 값으로 10억을 설정
+    // 노드의 개수(N), 간선의 개수(M), 거쳐 갈 노드(X), 최종 목적지 노드(K)
+    public static int n, m, x, k;
+    // 2차원 배열(그래프 표현)를 만들기
+    public static int[][] graph = new int[101][101];
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+
+        // 최단 거리 테이블을 모두 무한으로 초기화
+        for (int i = 0; i < 101; i++) {
+            Arrays.fill(graph[i], INF);
+        }
+
+        // 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
+        for (int a = 1; a <= n; a++) {
+            for (int b = 1; b <= n; b++) {
+                if (a == b) graph[a][b] = 0;
+            }
+        }
+
+        // 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
+        for (int i = 0; i < m; i++) {
+            // A와 B가 서로에게 가는 비용은 1이라고 설정
+            int a = sc.nextInt();
+            int b = sc.nextInt();
+            graph[a][b] = 1;
+            graph[b][a] = 1;
+        }
+
+        x = sc.nextInt();
+        k = sc.nextInt();
+
+        // 점화식에 따라 플로이드 워셜 알고리즘을 수행
+        for (int k = 1; k <= n; k++) {
+            for (int a = 1; a <= n; a++) {
+                for (int b = 1; b <= n; b++) {
+                    graph[a][b] = Math.min(graph[a][b], graph[a][k] + graph[k][b]);
+                }
+            }
+        }
+
+        // 수행된 결과를 출력
+        int distance = graph[1][k] + graph[k][x];
+
+        // 도달할 수 없는 경우, -1을 출력
+        if (distance >= INF) {
+            System.out.println(-1);
+        }
+        // 도달할 수 있다면, 최단 거리를 출력
+        else {
+            System.out.println(distance);
+        }
+    }
+}
\ No newline at end of file
diff --git a/9/4.py b/9/4.py
index accdd88..bffb30a 100644
--- a/9/4.py
+++ b/9/4.py
@@ -1,38 +1,38 @@
-INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정합니다.
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
 
-# 노드의 개수 및 간선의 개수를 입력 받습니다.
+# 노드의 개수 및 간선의 개수를 입력받기
 n, m = map(int, input().split())
-# 2차원 리스트(그래프 표현)를 만들고, 모든 값을 무한으로 초기화합니다.
+# 2차원 리스트(그래프 표현)를 만들고, 모든 값을 무한으로 초기화
 graph = [[INF] * (n + 1) for _ in range(n + 1)]
 
-# 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화합니다.
+# 자기 자신에서 자기 자신으로 가는 비용은 0으로 초기화
 for a in range(1, n + 1):
     for b in range(1, n + 1):
         if a == b:
             graph[a][b] = 0
 
-# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화합니다.
+# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
 for _ in range(m):
-    # A와 B가 서로에게 가는 비용은 1이라고 설정합니다.
+    # A와 B가 서로에게 가는 비용은 1이라고 설정
     a, b = map(int, input().split())
     graph[a][b] = 1
     graph[b][a] = 1
 
-# 거쳐 갈 노드 x와 최종 목적지 노드 k를 입력 받습니다.
+# 거쳐 갈 노드 X와 최종 목적지 노드 K를 입력받기
 x, k = map(int, input().split())
 
-# 점화식에 따라 플로이드 워셜 알고리즘을 수행합니다.
+# 점화식에 따라 플로이드 워셜 알고리즘을 수행
 for k in range(1, n + 1):
     for a in range(1, n + 1):
         for b in range(1, n + 1):
             graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])
 
-# 수행된 결과를 출력합니다.
+# 수행된 결과를 출력
 distance = graph[1][k] + graph[k][x]
 
-# 도달할 수 없는 경우, -1을 출력합니다.
+# 도달할 수 없는 경우, -1을 출력
 if distance >= 1e9:
     print("-1")
-# 도달할 수 있다면, 최단 거리를 출력합니다.
+# 도달할 수 있다면, 최단 거리를 출력
 else:
     print(distance)
diff --git a/9/5.cpp b/9/5.cpp
new file mode 100644
index 0000000..7049d9f
--- /dev/null
+++ b/9/5.cpp
@@ -0,0 +1,68 @@
+#include <bits/stdc++.h>
+#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정
+
+using namespace std;
+
+// 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start)
+int n, m, start;
+// 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열
+vector<pair<int, int> > graph[30001];
+// 최단 거리 테이블 만들기
+int d[30001];
+
+void dijkstra(int start) {
+    priority_queue<pair<int, int> > pq;
+    // 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+    pq.push({0, start});
+    d[start] = 0;
+    while (!pq.empty()) { // 큐가 비어있지 않다면
+        // 가장 최단 거리가 짧은 노드에 대한 정보 꺼내기
+        int dist = -pq.top().first; // 현재 노드까지의 비용 
+        int now = pq.top().second; // 현재 노드
+        pq.pop();
+        // 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+        if (d[now] < dist) continue;
+        // 현재 노드와 연결된 다른 인접한 노드들을 확인
+        for (int i = 0; i < graph[now].size(); i++) {
+            int cost = dist + graph[now][i].second;
+            // 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+            if (cost < d[graph[now][i].first]) {
+                d[graph[now][i].first] = cost;
+                pq.push(make_pair(-cost, graph[now][i].first));
+            }
+        }
+    }
+}
+
+int main(void) {
+    cin >> n >> m >> start;
+
+    // 모든 간선 정보를 입력받기
+    for (int i = 0; i < m; i++) {
+        int x, y, z;
+        cin >> x >> y >> z;
+        // X번 노드에서 Y번 노드로 가는 비용이 Z라는 의미
+        graph[x].push_back({y, z});
+    }
+
+    // 최단 거리 테이블을 모두 무한으로 초기화
+    fill(d, d + 30001, INF);
+    
+    // 다익스트라 알고리즘을 수행
+    dijkstra(start);
+
+    // 도달할 수 있는 노드의 개수
+    int count = 0;
+    // 도달할 수 있는 노드 중에서, 가장 멀리 있는 노드와의 최단 거리
+    int maxDistance = 0;
+    for (int i = 1; i <= n; i++) {
+        // 도달할 수 있는 노드인 경우
+        if (d[i] != INF) {
+            count += 1;
+            maxDistance = max(maxDistance, d[i]);
+        }
+    }
+
+    // 시작 노드는 제외해야 하므로 count - 1을 출력
+    cout << count - 1 << ' ' << maxDistance << '\n';
+}
\ No newline at end of file
diff --git a/9/5.java b/9/5.java
new file mode 100644
index 0000000..a0035cc
--- /dev/null
+++ b/9/5.java
@@ -0,0 +1,106 @@
+import java.util.*;
+
+class Node implements Comparable<Node> {
+
+    private int index;
+    private int distance;
+
+    public Node(int index, int distance) {
+        this.index = index;
+        this.distance = distance;
+    }
+
+    public int getIndex() {
+        return this.index;
+    }
+
+    public int getDistance() {
+        return this.distance;
+    }
+
+    // 거리(비용)가 짧은 것이 높은 우선순위를 가지도록 설정
+    @Override
+    public int compareTo(Node other) {
+        if (this.distance < other.distance) {
+            return -1;
+        }
+        return 1;
+    }
+}
+
+public class Main {
+    public static final int INF = (int) 1e9; // 무한을 의미하는 값으로 10억을 설정
+    // 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start)
+    public static int n, m, start;
+    // 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열
+    public static ArrayList<ArrayList<Node>> graph = new ArrayList<ArrayList<Node>>();
+    // 최단 거리 테이블 만들기
+    public static int[] d = new int[30001];
+
+    public static void dijkstra(int start) {
+        PriorityQueue<Node> pq = new PriorityQueue<>();
+        // 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
+        pq.offer(new Node(start, 0));
+        d[start] = 0;
+        while(!pq.isEmpty()) { // 큐가 비어있지 않다면
+            // 가장 최단 거리가 짧은 노드에 대한 정보 꺼내기
+            Node node = pq.poll();
+            int dist = node.getDistance(); // 현재 노드까지의 비용 
+            int now = node.getIndex(); // 현재 노드
+            // 현재 노드가 이미 처리된 적이 있는 노드라면 무시
+            if (d[now] < dist) continue;
+            // 현재 노드와 연결된 다른 인접한 노드들을 확인
+            for (int i = 0; i < graph.get(now).size(); i++) {
+                int cost = d[now] + graph.get(now).get(i).getDistance();
+                // 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
+                if (cost < d[graph.get(now).get(i).getIndex()]) {
+                    d[graph.get(now).get(i).getIndex()] = cost;
+                    pq.offer(new Node(graph.get(now).get(i).getIndex(), cost));
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner sc = new Scanner(System.in);
+
+        n = sc.nextInt();
+        m = sc.nextInt();
+        start = sc.nextInt();
+
+        // 그래프 초기화
+        for (int i = 0; i <= n; i++) {
+            graph.add(new ArrayList<Node>());
+        }
+        
+        // 모든 간선 정보를 입력받기
+        for (int i = 0; i < m; i++) {
+            int x = sc.nextInt();
+            int y = sc.nextInt();
+            int z = sc.nextInt();
+            // X번 노드에서 Y번 노드로 가는 비용이 Z라는 의미
+            graph.get(x).add(new Node(y, z));
+        }
+
+        // 최단 거리 테이블을 모두 무한으로 초기화
+        Arrays.fill(d, INF);
+        
+        // 다익스트라 알고리즘을 수행
+        dijkstra(start);
+
+        // 도달할 수 있는 노드의 개수
+        int count = 0;
+        // 도달할 수 있는 노드 중에서, 가장 멀리 있는 노드와의 최단 거리
+        int maxDistance = 0;
+        for (int i = 1; i <= n; i++) {
+            // 도달할 수 있는 노드인 경우
+            if (d[i] != INF) {
+                count += 1;
+                maxDistance = Math.max(maxDistance, d[i]);
+            }
+        }
+
+        // 시작 노드는 제외해야 하므로 count - 1을 출력
+        System.out.println((count - 1) + " " + maxDistance);
+    }
+}
\ No newline at end of file
diff --git a/9/5.py b/9/5.py
index e6fdb2a..9d780be 100644
--- a/9/5.py
+++ b/9/5.py
@@ -1,32 +1,32 @@
 import heapq
 import sys
 input = sys.stdin.readline
-INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정합니다.
+INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정
 
-# 노드의 개수, 간선의 개수, 시작 노드를 입력 받습니다.
+# 노드의 개수, 간선의 개수, 시작 노드를 입력받기
 n, m, start = map(int, input().split())
-# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만듭니다.
+# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기
 graph = [[] for i in range(n + 1)]
-# 최단 거리 테이블을 모두 무한으로 초기화합니다.
+# 최단 거리 테이블을 모두 무한으로 초기화
 distance = [INF] * (n + 1)
 
-# 모든 간선 정보를 입력 받습니다.
+# 모든 간선 정보를 입력받기
 for _ in range(m):
     x, y, z = map(int, input().split())
-    # a번 노드에서 b번 노드로 가는 비용이 z라는 의미입니다.
+    # X번 노드에서 Y번 노드로 가는 비용이 Z라는 의미
     graph[x].append((y, z))
 
 def dijkstra(start):
    q = []
-   # 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입합니다.
+   # 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입
    heapq.heappush(q, (0, start))
    distance[start] = 0
    while q: # 큐가 비어있지 않다면
-        # 가장 최단 거리가 짧은 노드에 대한 정보를 꺼냅니다.
+        # 가장 최단 거리가 짧은 노드에 대한 정보를 꺼내기
         dist, now = heapq.heappop(q)
         if distance[now] < dist:
             continue
-        # 현재 노드와 연결된 다른 인접한 노드들을 확인합니다.
+        # 현재 노드와 연결된 다른 인접한 노드들을 확인
         for i in graph[now]:
             cost = dist + i[1]
             # 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우
@@ -34,18 +34,18 @@ def dijkstra(start):
                 distance[i[0]] = cost
                 heapq.heappush(q, (cost, i[0]))
 
-# 다익스트라 알고리즘을 수행합니다.
+# 다익스트라 알고리즘을 수행
 dijkstra(start)
 
 # 도달할 수 있는 노드의 개수
 count = 0
 # 도달할 수 있는 노드 중에서, 가장 멀리 있는 노드와의 최단 거리
 max_distance = 0
-for i in distance:
+for d in distance:
     # 도달할 수 있는 노드인 경우
-    if i != 1e9:
+    if d != 1e9:
         count += 1
-        max_distance = max(max_distance, i)
+        max_distance = max(max_distance, d)
 
-# 시작 노드는 제외해야 하므로 count - 1을 출력합니다.
+# 시작 노드는 제외해야 하므로 count - 1을 출력
 print(count - 1, max_distance)
diff --git a/README.md b/README.md
index 49fd4c3..8adf9d3 100644
--- a/README.md
+++ b/README.md
@@ -1,198 +1,262 @@
-### 알고리즘 코딩 테스트 합격을 위한 파이썬 비법 노트
+### 이것이 취업을 위한 코딩 테스트다 with Python
+> 취업과 이직을 결정하는 알고리즘 인터뷰 완벽 가이드 (2020년 08월 05일 정식 출시)
+
+* 이 저장소는 <b>이것이 취업을 위한 코딩 테스트다 with Python</b> (나동빈 저, 한빛미디어) 전체 소스코드를 포함합니다.
+* 본 책은 Python 3.7 문법을 활용하였으나, 추가적으로 Java, C++11 소스코드를 제공합니다.
+* 책 내용 및 소스코드와 관련한 궁금한 점은 [Issues](https://github.com/ndb796/python-for-coding-test/issues) 탭을 이용하여 남겨주세요.
+* 책의 오류 사항을 발견하시면 dongbinna@postech.ac.kr로 보내주시면 감사하겠습니다.
+    * 이 경우, 원하신다면 <b>[정오표](/notice.md)</b>에 독자님의 이름(혹은 아이디)을 함께 기재해드립니다.
+* 이 책을 이용해 강의를 진행하시는 교수/선생님/강사/동아리장 님들을 위해 강의용 PPT를 제공합니다. (준비중)
+* 전체 동영상 강의는 2020년 8 ~ 9월에 걸친 유튜브 라이브 강의를 진행하고 편집 후에 업로드 될 예정입니다.
+* 책 구매 링크: [한빛미디어](http://hanbit.co.kr/store/books/look.php?p_code=B8945183661) / [YES24](http://www.yes24.com/Product/Goods/91433923) / [교보문고](http://www.kyobobook.co.kr/product/detailViewKor.laf?barcode=9791162243077) / [알라딘](https://www.aladin.co.kr/shop/wproduct.aspx?ISBN=K342631735)
 
-* (출판 예정) [가제] 알고리즘 코딩 테스트 합격을 위한 파이썬 비법 노트 (한빛 미디어, 나동빈 저) 소스코드 저장소입니다.
-* 본 책은 Python 3.7 문법을 활용하였으나, 일부 예제에 대하여 C++11 소스코드를 추가적으로 제공할 예정입니다.
-* 소스코드와 관련한 궁금한 점이나 오류 관련 문의는 [Issues](https://github.com/ndb796/python-for-coding-test/issues) 탭을 이용하여 남겨주세요.
+<hr>
+
+### 대기업 코딩 테스트 문제 적중 관련
+
+* 최근 2021 K사 공채 코딩 테스트 1차 합격 커트라인은 3문제 ~ 3.5문제(부분점수 포함)로 예상됩니다.
+* 저자 또한 코딩 테스트에 참여해 보았고, <b>파이썬만 이용하여</b> 알고리즘 코딩 테스트에 합격할 수 있었습니다.
+* 특히 아래 두 문제는 본 책의 파이썬 코드를 참고하여 쉽게 해결할 수 있었습니다.
+
+* <b>3번 문제 (이진 탐색)</b>: 책의 15장 [정렬된 배열에서 특정 수의 개수 구하기](/15/1.py) 알고리즘을 활용하면 쉽게 풀 수 있는 문제였습니다.
+    * 파이썬의 bisect_left 함수를 활용합니다.
+* <b>4번 (플로이드 워셜)</b>: 책의 9장 [미래 도시](/9/4.py) 문제와 접근 방법 및 아이디어가 사실상 동일한 문제입니다.
+    * 특정한 중간 지점을 거쳐 갈 때의 최단 경로 알고리즘으로 볼 수 있습니다.
+    * 저자 개인적으로도 이 문제는 보자마자 풀어서 7분 이내로 풀 수 있었습니다.
 
 <hr>
 
-### Part 1 코딩 테스트 시작하기
+### 도와주신 분들
+
+* 베타 리뷰어 님들: 김민철, 안수빈, 정한길, 황성호 외 10분
+* [백준 온라인 저지(BOJ)](https://www.acmicpc.net/)의 일부 문제를 사용할 수 있도록 허락해주고, 개인적으로 많은 도움을 주신 최백준 님
+* 2019, 2020 K사 문제를 책에 수록할 수 있도록 허락해주신 (주)그렙 [프로그래머스](https://programmers.co.kr/)
+    * PPL: [프로그래머스 알고리즘 문제 풀이 강의](https://programmers.co.kr/learn/courses/10336)
+
+### 시작하며
+
+* [지은이의 글 및 리뷰어의 글](https://blog.naver.com/ndb796/222048713087)
+
+### Part 1 코딩 테스트, 무엇을 어떻게 준비할까?
 
 #### 1장 코딩 테스트 개요
 
-#### 2장 코딩 테스트 유형 분석
+* 코딩 테스트 개념과 배경
+* 실습 환경 구축하기
+* 복잡도
+    * [파이썬 수행 시간 측정 방법](/1/1.py)
+    * [선택 정렬과 기본 정렬 라이브러리의 수행 시간 비교](/1/2.py)
 
-### Part 2 알고리즘 이론과 실전
+#### 2장 16~20년 코딩 테스트 기출문제 유형 분석
+
+* 최신 출제 경향과 준비 방향
+* 연도별 코딩 테스트 유형 분석
+
+#### GUIDE: 성공적인 취업을 위한 가이드
+
+* 채용 프로세스
+* 기술 면접의 대표적인 유형
+* 기술 면접 준비
+* 알고리즘 문제 풀이 사이트
+* 커뮤니티 사이트
+
+### Part 2 주요 알고리즘 이론과 실전 문제
 
 #### 3장 그리디
 
 * 이론
-    * 거스름돈 문제: [Python 3.7 코드](/3/1.py)
+    * 당장 좋은 것만 선택하는 그리디
+    * 거스름돈 문제: ([Python 3.7 코드](/3/1.py) / [C++ 코드](/3/1.cpp) / [Java 코드](/3/1.java))
 * 실전
-    * 동빈이의 큰 수의 법칙: [Python 3.7 코드](/3/2.py)
-    * 숫자 카드게임: [Python 3.7 코드](/3/3.py)
-    * 1이 될 때까지: [Python 3.7 코드](/3/4.py)
+    * 동빈이의 큰 수의 법칙: ([Python 3.7 코드](/3/2.py) / [C++ 코드](/3/2.cpp) / [Java 코드](/3/2.java))
+    * 숫자 카드게임: ([Python 3.7 코드](/3/4.py) / [C++ 코드](/3/4.cpp) / [Java 코드](/3/4.java))
+    * 1이 될 때까지: ([Python 3.7 코드](/3/6.py) / [C++ 코드](/3/6.cpp) / [Java 코드](/3/6.java))
 
 #### 4장 구현
 
 * 이론
-    * 상하좌우: [Python 3.7 코드](/4/1.py)
-    * 시각: [Python 3.7 코드](/4/2.py)
+    * 아이디어를 코드로 바꾸는 구현
+    * 상하좌우: ([Python 3.7 코드](/4/1.py) / [C++ 코드](/4/1.cpp) / [Java 코드](/4/1.java))
+    * 시각: ([Python 3.7 코드](/4/2.py) / [C++ 코드](/4/2.cpp) / [Java 코드](/4/2.java))
 * 실전
-    * 왕실의 나이트: [Python 3.7 코드](/4/3.py)
-    * 게임 개발: [Python 3.7 코드](/4/4.py)
+    * 왕실의 나이트: ([Python 3.7 코드](/4/3.py) / [C++ 코드](/4/3.cpp) / [Java 코드](/4/3.java))
+    * 게임 개발: ([Python 3.7 코드](/4/4.py) / [C++ 코드](/4/4.cpp) / [Java 코드](/4/4.java))
 
 #### 5장 DFS/BFS
 
 * 이론
-    * 스택 구현 예제: [Python 3.7 코드](/5/1.py)
-    * 큐 구현 예제: [Python 3.7 코드](/5/2.py)
-    * 무한히 반복되는 재귀함수 예시: [Python 3.7 코드](/5/3.py)
-    * 재귀함수의 종료 조건: [Python 3.7 코드](/5/4.py)
-    * 팩토리얼 구현하기: [Python 3.7 코드](/5/5.py)
-    * 인접 행렬 예시: [Python 3.7 코드](/5/6.py)
-    * 인접 리스트 예시: [Python 3.7 코드](/5/7.py)
-    * DFS: [Python 3.7 코드](/5/8.py)
-    * BFS: [Python 3.7 코드](/5/9.py)
+    * 꼭 필요한 자료구조 기초
+    * 탐색 알고리즘 DFS/BFS
+    * 스택 구현 예제: ([Python 3.7 코드](/5/1.py) / [C++ 코드](/5/1.cpp) / [Java 코드](/5/1.java))
+    * 큐 구현 예제: ([Python 3.7 코드](/5/2.py) / [C++ 코드](/5/2.cpp) / [Java 코드](/5/2.java))
+    * 무한히 반복되는 재귀함수 예제: ([Python 3.7 코드](/5/3.py) / [C++ 코드](/5/3.cpp) / [Java 코드](/5/3.java))
+    * 재귀함수의 종료 조건 예제: ([Python 3.7 코드](/5/4.py) / [C++ 코드](/5/4.cpp) / [Java 코드](/5/4.java))
+    * 2가지 방식으로 구현한 팩토리얼 예제: ([Python 3.7 코드](/5/5.py) / [C++ 코드](/5/5.cpp) / [Java 코드](/5/5.java))
+    * 인접 행렬 예제: ([Python 3.7 코드](/5/6.py) / [C++ 코드](/5/6.cpp) / [Java 코드](/5/6.java))
+    * 인접 리스트 예제: ([Python 3.7 코드](/5/7.py) / [C++ 코드](/5/7.cpp) / [Java 코드](/5/7.java))
+    * DFS: ([Python 3.7 코드](/5/8.py) / [C++ 코드](/5/8.cpp) / [Java 코드](/5/8.java))
+    * BFS: ([Python 3.7 코드](/5/9.py) / [C++ 코드](/5/9.cpp) / [Java 코드](/5/9.java))
 * 실전
-    * 음료수 얼려 먹기: [Python 3.7 코드](/5/10.py)
-    * 미로 탈출: [Python 3.7 코드](/5/11.py)
+    * 음료수 얼려 먹기: ([Python 3.7 코드](/5/10.py) / [C++ 코드](/5/10.cpp) / [Java 코드](/5/10.java))
+    * 미로 탈출: ([Python 3.7 코드](/5/11.py) / [C++ 코드](/5/11.cpp) / [Java 코드](/5/11.java))
 
 #### 6장 정렬
 
 * 이론
-    * 선택 정렬: [Python 3.7 코드](/6/1.py)
-    * 삽입 정렬: [Python 3.7 코드](/6/2.py)
-    * 퀵 정렬: [Python 3.7 코드](/6/3.py)
-    * 계수 정렬: [Python 3.7 코드](/6/4.py)
-    * 정렬 라이브러리 기본 예제: [Python 3.7 코드](/6/5.py)
-    * 정렬 라이브러리 키(Key) 기준 정렬 예제: [Python 3.7 코드](/6/6.py)
+    * 기준에 따라서 데이터를 정렬
+    * 선택 정렬: ([Python 3.7 코드](/6/1.py) / [C++ 코드](/6/1.cpp) / [Java 코드](/6/1.java))
+    * 스와프(Swap): ([Python 3.7 코드](/6/2.py) / [C++ 코드](/6/2.cpp) / [Java 코드](/6/2.java))
+    * 삽입 정렬: ([Python 3.7 코드](/6/3.py) / [C++ 코드](/6/3.cpp) / [Java 코드](/6/3.java))
+    * 퀵 정렬: ([Python 3.7 코드](/6/4.py) / [C++ 코드](/6/4.cpp) / [Java 코드](/6/4.java))
+    * 파이썬의 장점을 살린 퀵 정렬: [Python 3.7 코드](/6/5.py)
+    * 계수 정렬: ([Python 3.7 코드](/6/6.py) / [C++ 코드](/6/6.cpp) / [Java 코드](/6/6.java))
+    * 정렬 라이브러리 기본 예제: ([Python 3.7 코드](/6/7.py) / [C++ 코드](/6/7.cpp) / [Java 코드](/6/7.java))
+    * 정렬 라이브러리 키(Key) 기준 정렬 예제: ([Python 3.7 코드](/6/9.py) / [C++ 코드](/6/9.cpp) / [Java 코드](/6/9.java))
 * 실전
-    * 위에서 아래로: [Python 3.7 코드](/6/7.py)
-    * 성적이 낮은 순서대로 학생 출력하기: [Python 3.7 코드](/6/8.py)
-    * 재고 정리: [Python 3.7 코드](/6/9.py)
+    * 위에서 아래로: ([Python 3.7 코드](/6/10.py) / [C++ 코드](/6/10.cpp) / [Java 코드](/6/10.java))
+    * 성적이 낮은 순서대로 학생 출력하기: ([Python 3.7 코드](/6/11.py) / [C++ 코드](/6/11.cpp) / [Java 코드](/6/11.java))
+    * 두 배열의 원소 교체: ([Python 3.7 코드](/6/12.py) / [C++ 코드](/6/12.cpp) / [Java 코드](/6/12.java))
 
 #### 7장 이진 탐색
 
 * 이론
-    * 순차 탐색: [Python 3.7 코드](/7/1.py)
-    * 재귀 함수를 이용한 이진 탐색: [Python 3.7 코드](/7/2.py)
-    * 반복문을 이용한 이진 탐색: [Python 3.7 코드](/7/3.py)
-    * 빠르게 입력 받기: [Python 3.7 코드](/7/4.py)
+    * 범위를 반씩 좁혀가는 탐색
+    * 순차 탐색: ([Python 3.7 코드](/7/1.py) / [C++ 코드](/7/1.cpp) / [Java 코드](/7/1.java))
+    * 재귀 함수를 이용한 이진 탐색: ([Python 3.7 코드](/7/2.py) / [C++ 코드](/7/2.cpp) / [Java 코드](/7/2.java))
+    * 반복문을 이용한 이진 탐색: ([Python 3.7 코드](/7/3.py) / [C++ 코드](/7/3.cpp) / [Java 코드](/7/3.java))
+    * 파이썬에서 빠르게 입력 받기: [Python 3.7 코드](/7/4.py)
 * 실전
     * 부품 찾기
-        * 이진 탐색으로 해결: [Python 3.7 코드](/7/5.py)
-        * 계수 정렬로 해결: [Python 3.7 코드](/7/6.py)
-        * 집합(Set) 자료형으로 해결: [Python 3.7 코드](/7/7.py)
-    * 떡볶이 만들기: [Python 3.7 코드](/7/8.py)
+        * 이진 탐색으로 해결: ([Python 3.7 코드](/7/5.py) / [C++ 코드](/7/5.cpp) / [Java 코드](/7/5.java))
+        * 계수 정렬로 해결: ([Python 3.7 코드](/7/6.py) / [C++ 코드](/7/6.cpp) / [Java 코드](/7/6.java))
+        * 집합(Set) 자료형으로 해결: ([Python 3.7 코드](/7/7.py) / [C++ 코드](/7/7.cpp) / [Java 코드](/7/7.java))
+    * 떡볶이 떡 만들기: ([Python 3.7 코드](/7/8.py) / [C++ 코드](/7/8.cpp) / [Java 코드](/7/8.java))
 
 #### 8장 다이나믹 프로그래밍
 
 * 이론
-    * 비효율적인 피보나치 수열 구현: [Python 3.7 코드](/8/1.py)
-    * 피보나치 수열 (Top-bottom): [Python 3.7 코드](/8/2.py)
-    * 피보나치 수열 (Bottom-top): [Python 3.7 코드](/8/3.py)
+    * 비효율적인 피보나치 수열 구현: ([Python 3.7 코드](/8/1.py) / [C++ 코드](/8/1.cpp) / [Java 코드](/8/1.java))
+    * 피보나치 수열 (Top-bottom): ([Python 3.7 코드](/8/2.py) / [C++ 코드](/8/2.cpp) / [Java 코드](/8/2.java))
+    * 피보나치 수열 (Bottom-top): ([Python 3.7 코드](/8/4.py) / [C++ 코드](/8/4.cpp) / [Java 코드](/8/4.java))
 * 실전
-    * 1로 만들기: [Python 3.7 코드](/8/4.py)
-    * 개미 전사: [Python 3.7 코드](/8/5.py)
-    * 바닥 공사: [Python 3.7 코드](/8/6.py)
-    * 효율적인 화폐 구성: [Python 3.7 코드](/8/7.py)
+    * 1로 만들기: ([Python 3.7 코드](/8/5.py) / [C++ 코드](/8/5.cpp) / [Java 코드](/8/5.java))
+    * 개미 전사: ([Python 3.7 코드](/8/6.py) / [C++ 코드](/8/6.cpp) / [Java 코드](/8/6.java))
+    * 바닥 공사: ([Python 3.7 코드](/8/7.py) / [C++ 코드](/8/7.cpp) / [Java 코드](/8/7.java))
+    * 효율적인 화폐 구성: ([Python 3.7 코드](/8/8.py) / [C++ 코드](/8/8.cpp) / [Java 코드](/8/8.java))
 
 #### 9장 최단 경로
 
 * 이론
-    * 간단한 다익스트라 알고리즘: [Python 3.7 코드](/9/1.py)
-    * 개선된 다익스트라 알고리즘 (우선순위 큐): [Python 3.7 코드](/9/2.py)
-    * 플로이드 워셜 알고리즘: [Python 3.7 코드](/9/3.py)
+    * 가장 빠른 길 찾기
+    * 간단한 다익스트라 알고리즘: ([Python 3.7 코드](/9/1.py) / [C++ 코드](/9/1.cpp) / [Java 코드](/9/1.java))
+    * 개선된 다익스트라 알고리즘 (우선순위 큐): ([Python 3.7 코드](/9/2.py) / [C++ 코드](/9/2.cpp) / [Java 코드](/9/2.java))
+    * 플로이드 워셜 알고리즘: ([Python 3.7 코드](/9/3.py) / [C++ 코드](/9/3.cpp) / [Java 코드](/9/3.java))
 * 실전
-    * 미래 도시: [Python 3.7 코드](/9/4.py)
-    * 전보: [Python 3.7 코드](/9/5.py)
+    * 미래 도시: ([Python 3.7 코드](/9/4.py) / [C++ 코드](/9/4.cpp) / [Java 코드](/9/4.java))
+    * 전보: ([Python 3.7 코드](/9/5.py) / [C++ 코드](/9/5.cpp) / [Java 코드](/9/5.java))
 
 #### 10장 기타 그래프 이론
 
 * 이론
-    * 간단한 서로소 집합 알고리즘: [Python 3.7 코드](/10/1.py)
-    * 개선된 서로소 집합 알고리즘 (경로 압축): [Python 3.7 코드](/10/2.py)
-    * 서로소 집합을 활용한 사이클 판별: [Python 3.7 코드](/10/3.py)
-    * 크루스칼 알고리즘: [Python 3.7 코드](/10/4.py)
-    * 위상 정렬: [Python 3.7 코드](/10/5.py)
+    * 다양한 그래프 알고리즘
+    * 간단한 서로소 집합 알고리즘: ([Python 3.7 코드](/10/1.py) / [C++ 코드](/10/1.cpp) / [Java 코드](/10/1.java))
+    * 개선된 서로소 집합 알고리즘 (경로 압축): ([Python 3.7 코드](/10/3.py) / [C++ 코드](/10/3.cpp) / [Java 코드](/10/3.java))
+    * 서로소 집합을 활용한 사이클 판별: ([Python 3.7 코드](/10/4.py) / [C++ 코드](/10/4.cpp) / [Java 코드](/10/4.java))
+    * 크루스칼 알고리즘: ([Python 3.7 코드](/10/5.py) / [C++ 코드](/10/5.cpp) / [Java 코드](/10/5.java))
+    * 위상 정렬: ([Python 3.7 코드](/10/6.py) / [C++ 코드](/10/6.cpp) / [Java 코드](/10/6.java))
 * 실전
-    * 팀 결성: [Python 3.7 코드](/10/6.py)
-    * 도시 분할 계획: [Python 3.7 코드](/10/7.py)
-    * 커리큘럼: [Python 3.7 코드](/10/8.py)
+    * 팀 결성: ([Python 3.7 코드](/10/7.py) / [C++ 코드](/10/7.cpp) / [Java 코드](/10/7.java))
+    * 도시 분할 계획: ([Python 3.7 코드](/10/8.py) / [C++ 코드](/10/8.cpp) / [Java 코드](/10/8.java))
+    * 커리큘럼: ([Python 3.7 코드](/10/9.py) / [C++ 코드](/10/9.cpp) / [Java 코드](/10/9.java))
 
-### Part 3 코딩 테스트 문제집
+### Part 3 알고리즘 유형별 기출문제
 
 #### 11장 그리디
 
-* 모험가 (핵심 유형): [Python 3.7 코드](/11/1.py)
-* 곱하기 혹은 더하기 (Facebook 인터뷰 기출): [Python 3.7 코드](/11/2.py)
-* [문자열 뒤집기](https://www.acmicpc.net/problem/1439) (핵심 유형): [Python 3.7 코드](/11/3.py)
-* 만들 수 없는 금액 (K 대회 기출): [Python 3.7 코드](/11/4.py)
-* 볼링공 고르기 (S 기관 입학 테스트): [Python 3.7 코드](/11/5.py)
-* [무지의 먹방 라이브](https://www.acmicpc.net/problem/2437) (카카오): [Python 3.7 코드](/11/6.py)
+* 모험가 길드 (핵심 유형): ([Python 3.7 코드](/11/1.py) / [C++ 코드](/11/1.cpp) / [Java 코드](/11/1.java))
+* 곱하기 혹은 더하기 (Facebook 인터뷰 기출): ([Python 3.7 코드](/11/2.py) / [C++ 코드](/11/2.cpp) / [Java 코드](/11/2.java))
+* [문자열 뒤집기](https://www.acmicpc.net/problem/1439) (핵심 유형): ([Python 3.7 코드](/11/3.py) / [C++ 코드](/11/3.cpp) / [Java 코드](/11/3.java))
+* 만들 수 없는 금액 (K 대회 기출): ([Python 3.7 코드](/11/4.py) / [C++ 코드](/11/4.cpp) / [Java 코드](/11/4.java))
+* 볼링공 고르기 (S 기관 입학 테스트): ([Python 3.7 코드](/11/5.py) / [C++ 코드](/11/5.cpp) / [Java 코드](/11/5.java))
+* [무지의 먹방 라이브](https://programmers.co.kr/learn/courses/30/lessons/42891) (카카오): ([Python 3.7 코드](/11/6.py) / [C++ 코드](/11/6.cpp) / [Java 코드](/11/6.java))
 
 #### 12장 구현
 
-* [럭키 스트레이트](https://www.acmicpc.net/problem/18406) (핵심 유형): [Python 3.7 코드](/12/1.py)
-* 문자열 재정렬 (Facebook 인터뷰 기출): [Python 3.7 코드](/12/2.py)
-* [문자열 압축](https://programmers.co.kr/learn/courses/30/lessons/60057) (카카오): [Python 3.7 코드](/12/3.py)
-* [자물쇠와 열쇠](https://programmers.co.kr/learn/courses/30/lessons/60059) (카카오): [Python 3.7 코드](/12/4.py)
-* [뱀](https://www.acmicpc.net/problem/3190) (삼성): [Python 3.7 코드](/12/5.py)
-* [기둥과 보](https://programmers.co.kr/learn/courses/30/lessons/60061) (카카오): [Python 3.7 코드](/12/6.py)
-* [치킨 배달](https://www.acmicpc.net/problem/15686) (삼성): [Python 3.7 코드](/12/7.py)
-* [외벽 점검](https://programmers.co.kr/learn/courses/30/lessons/60062) (카카오): [Python 3.7 코드](/12/8.py)
+* [럭키 스트레이트](https://www.acmicpc.net/problem/18406) (핵심 유형): ([Python 3.7 코드](/12/1.py) / [C++ 코드](/12/1.cpp) / [Java 코드](/12/1.java))
+* 문자열 재정렬 (Facebook 인터뷰 기출): ([Python 3.7 코드](/12/2.py) / [C++ 코드](/12/2.cpp) / [Java 코드](/12/2.java))
+* [문자열 압축](https://programmers.co.kr/learn/courses/30/lessons/60057) (카카오): ([Python 3.7 코드](/12/3.py) / [C++ 코드](/12/3.cpp) / [Java 코드](/12/3.java))
+* [자물쇠와 열쇠](https://programmers.co.kr/learn/courses/30/lessons/60059) (카카오): ([Python 3.7 코드](/12/4.py) / [C++ 코드](/12/4.cpp) / [Java 코드](/12/4.java))
+* [뱀](https://www.acmicpc.net/problem/3190) (삼성): ([Python 3.7 코드](/12/5.py) / [C++ 코드](/12/5.cpp) / [Java 코드](/12/5.java))
+* [기둥과 보 설치](https://programmers.co.kr/learn/courses/30/lessons/60061) (카카오): ([Python 3.7 코드](/12/6.py) / [C++ 코드](/12/6.cpp) / [Java 코드](/12/6.java))
+* [치킨 배달](https://www.acmicpc.net/problem/15686) (삼성): ([Python 3.7 코드](/12/7.py) / [C++ 코드](/12/7.cpp) / [Java 코드](/12/7.java))
+* [외벽 점검](https://programmers.co.kr/learn/courses/30/lessons/60062) (카카오): ([Python 3.7 코드](/12/8.py) / [C++ 코드](/12/8.cpp) / [Java 코드](/12/8.java))
 
 #### 13장 DFS/BFS
 
-* [특정 거리의 도시 찾기](https://www.acmicpc.net/problem/18352) (핵심 유형): [Python 3.7 코드](/13/1.py)
-* [연구소](https://www.acmicpc.net/problem/14502) (삼성): [Python 3.7 코드](/13/2.py)
-* [경쟁적 전염](https://www.acmicpc.net/problem/18405) (핵심 유형): [Python 3.7 코드](/13/3.py)
-* [괄호 변환](https://programmers.co.kr/learn/courses/30/lessons/60058) (카카오): [Python 3.7 코드](/13/4.py)
-* [연산자 끼워넣기](https://www.acmicpc.net/problem/14888) (삼성): [Python 3.7 코드](/13/5.py)
-* [감시 피하기](https://www.acmicpc.net/problem/18428) (핵심 유형): [Python 3.7 코드](/13/6.py)
-* [인구 이동](https://www.acmicpc.net/problem/16234) (삼성): [Python 3.7 코드](/13/7.py)
-* [블록 이동하기](https://programmers.co.kr/learn/courses/30/lessons/60063) (카카오): [Python 3.7 코드](/13/8.py)
+* [특정 거리의 도시 찾기](https://www.acmicpc.net/problem/18352) (핵심 유형): ([Python 3.7 코드](/13/1.py) / [C++ 코드](/13/1.cpp) / [Java 코드](/13/1.java))
+* [연구소](https://www.acmicpc.net/problem/14502) (삼성): ([Python 3.7 코드](/13/2.py) / [C++ 코드](/13/2.cpp) / [Java 코드](/13/2.java))
+* [경쟁적 전염](https://www.acmicpc.net/problem/18405) (핵심 유형): ([Python 3.7 코드](/13/3.py) / [C++ 코드](/13/3.cpp) / [Java 코드](/13/3.java))
+* [괄호 변환](https://programmers.co.kr/learn/courses/30/lessons/60058) (카카오): ([Python 3.7 코드](/13/4.py) / [C++ 코드](/13/4.cpp) / [Java 코드](/13/4.java))
+* [연산자 끼워 넣기](https://www.acmicpc.net/problem/14888) (삼성): ([Python 3.7 코드](/13/5.py) / [C++ 코드](/13/5.cpp) / [Java 코드](/13/5.java))
+* [감시 피하기](https://www.acmicpc.net/problem/18428) (핵심 유형): ([Python 3.7 코드](/13/6.py) / [C++ 코드](/13/6.cpp) / [Java 코드](/13/6.java))
+* [인구 이동](https://www.acmicpc.net/problem/16234) (삼성): ([Python 3.7 코드](/13/7.py) / [C++ 코드](/13/7.cpp) / [Java 코드](/13/7.java))
+* [블록 이동하기](https://programmers.co.kr/learn/courses/30/lessons/60063) (카카오): ([Python 3.7 코드](/13/8.py) / [C++ 코드](/13/8.cpp) / [Java 코드](/13/8.java))
 
 #### 14장 정렬
 
-* [국영수](https://www.acmicpc.net/problem/10825) (핵심 유형): [Python 3.7 코드](/14/1.py)
-* [안테나](https://www.acmicpc.net/problem/18310) (국내 S 교육 기관 선발 평가): [Python 3.7 코드](/14/2.py)
-* [실패율](https://programmers.co.kr/learn/courses/30/lessons/42889) (카카오): [Python 3.7 코드](/14/3.py)
-* [카드 정렬하기](https://www.acmicpc.net/problem/1715) (핵심 유형): [Python 3.7 코드](/14/4.py)
+* [국영수](https://www.acmicpc.net/problem/10825) (핵심 유형): ([Python 3.7 코드](/14/1.py) / [C++ 코드](/14/1.cpp) / [Java 코드](/14/1.java))
+* [안테나](https://www.acmicpc.net/problem/18310) (국내 S 교육 기관 선발 평가): ([Python 3.7 코드](/14/2.py) / [C++ 코드](/14/2.cpp) / [Java 코드](/14/2.java))
+* [실패율](https://programmers.co.kr/learn/courses/30/lessons/42889) (카카오): ([Python 3.7 코드](/14/3.py) / [C++ 코드](/14/3.cpp) / [Java 코드](/14/3.java))
+* [카드 정렬하기](https://www.acmicpc.net/problem/1715) (핵심 유형): ([Python 3.7 코드](/14/4.py) / [C++ 코드](/14/4.cpp) / [Java 코드](/14/4.java))
 
 #### 15장 이진 탐색
 
-* 정렬된 배열에서 특정 수의 개수 구하기 (Zoho 인터뷰 기출): [Python 3.7 코드](/15/1.py)
-* 고정점 찾기 (Amazon 인터뷰 기출): [Python 3.7 코드](/15/2.py)
-* 영역 다툼 (핵심 유형): [Python 3.7 코드](/15/3.py)
-* [가사 검색](https://programmers.co.kr/learn/courses/30/lessons/60060) (카카오): [Python 3.7 코드](/15/4.py)
+* 정렬된 배열에서 특정 수의 개수 구하기 (Zoho 인터뷰 기출): ([Python 3.7 코드](/15/1.py) / [C++ 코드](/15/1.cpp) / [Java 코드](/15/1.java))
+* 고정점 찾기 (Amazon 인터뷰 기출): ([Python 3.7 코드](/15/2.py) / [C++ 코드](/15/2.cpp) / [Java 코드](/15/2.java))
+* [공유기 설치](https://www.acmicpc.net/problem/2110) (핵심 유형): ([Python 3.7 코드](/15/3.py) / [C++ 코드](/15/3.cpp) / [Java 코드](/15/3.java))
+* [가사 검색](https://programmers.co.kr/learn/courses/30/lessons/60060) (카카오): ([Python 3.7 코드](/15/4.py) / [C++ 코드](/15/4.cpp) / [Java 코드](/15/4.java))
 
 #### 16장 다이나믹 프로그래밍
 
-* 금광 (Flipkart 인터뷰 기출): [Python 3.7 코드](/16/1.py)
-* [정수 삼각형](https://www.acmicpc.net/problem/1932) (IOI): [Python 3.7 코드](/16/2.py)
-* [퇴사](https://www.acmicpc.net/problem/14501) (삼성): [Python 3.7 코드](/16/3.py)
-* [병사 배치하기](https://www.acmicpc.net/problem/18353) (핵심 유형): [Python 3.7 코드](/16/4.py)
-* 못생긴 수 (Google 인터뷰 기출): [Python 3.7 코드](/16/5.py)
-* 편집 거리 (Goldman Sachs 인터뷰 기출): [Python 3.7 코드](/16/6.py)
+* 금광 (Flipkart 인터뷰 기출): ([Python 3.7 코드](/16/1.py) / [C++ 코드](/16/1.cpp) / [Java 코드](/16/1.java))
+* [정수 삼각형](https://www.acmicpc.net/problem/1932) (IOI): ([Python 3.7 코드](/16/2.py) / [C++ 코드](/16/2.cpp) / [Java 코드](/16/2.java))
+* [퇴사](https://www.acmicpc.net/problem/14501) (삼성): ([Python 3.7 코드](/16/3.py) / [C++ 코드](/16/3.cpp) / [Java 코드](/16/3.java))
+* [병사 배치하기](https://www.acmicpc.net/problem/18353) (핵심 유형): ([Python 3.7 코드](/16/4.py) / [C++ 코드](/16/4.cpp) / [Java 코드](/16/4.java))
+* 못생긴 수 (Google 인터뷰 기출): ([Python 3.7 코드](/16/5.py) / [C++ 코드](/16/5.cpp) / [Java 코드](/16/5.java))
+* 편집 거리 (Goldman Sachs 인터뷰 기출): ([Python 3.7 코드](/16/6.py) / [C++ 코드](/16/6.cpp) / [Java 코드](/16/6.java))
 
 #### 17장 최단 경로
 
-* [플로이드](https://www.acmicpc.net/problem/11404) (핵심 유형): [Python 3.7 코드]
-* 정확한 순위 (K 대회 기출): [Python 3.7 코드]
-* 장애물 경주 (ICPC): [Python 3.7 코드]
-* 숨바꼭질 (USACO): [Python 3.7 코드]
+* [플로이드](https://www.acmicpc.net/problem/11404) (핵심 유형): ([Python 3.7 코드](/17/1.py) / [C++ 코드](/17/1.cpp) / [Java 코드](/17/1.java))
+* 정확한 순위 (K 대회 기출): ([Python 3.7 코드](/17/2.py) / [C++ 코드](/17/2.cpp) / [Java 코드](/17/2.java))
+* 화성 탐사 (ICPC): ([Python 3.7 코드](/17/3.py) / [C++ 코드](/17/3.cpp) / [Java 코드](/17/3.java))
+* 숨바꼭질 (USACO): ([Python 3.7 코드](/17/4.py) / [C++ 코드](/17/4.cpp) / [Java 코드](/17/4.java))
 
 #### 18장 기타 그래프 이론
 
-* 사랑의 메신저 (핵심 유형): [Python 3.7 코드]
-* 탑승구 (CCC): [Python 3.7 코드]
-* 어두운 길 (University of Ulm Local Contest): [Python 3.7 코드]
-* [행성 터널](https://www.acmicpc.net/problem/2887) (COCI): [Python 3.7 코드]
-* [최종 순위](https://www.acmicpc.net/problem/3665) (ICPC): [Python 3.7 코드]
+* 여행 계획 (핵심 유형): ([Python 3.7 코드](/18/1.py) / [C++ 코드](/18/1.cpp) / [Java 코드](/18/1.java))
+* 탑승구 (CCC): ([Python 3.7 코드](/18/2.py) / [C++ 코드](/18/2.cpp) / [Java 코드](/18/2.java))
+* 어두운 길 (University of Ulm Local Contest): ([Python 3.7 코드](/18/3.py) / [C++ 코드](/18/3.cpp) / [Java 코드](/18/3.java))
+* [행성 터널](https://www.acmicpc.net/problem/2887) (COCI): ([Python 3.7 코드](/18/4.py) / [C++ 코드](/18/4.cpp) / [Java 코드](/18/4.java))
+* [최종 순위](https://www.acmicpc.net/problem/3665) (ICPC): ([Python 3.7 코드](/18/5.py) / [C++ 코드](/18/5.cpp) / [Java 코드](/18/5.java))
+
+#### 19장 2020년 상반기 삼성전자 기출문제
+
+* [아기 상어](https://www.acmicpc.net/problem/16236) (삼성): [Python 3.7 코드](19/1.py)
+* [청소년 상어](https://www.acmicpc.net/problem/19236) (삼성): [Python 3.7 코드](19/2.py)
+* [어른 상어](https://www.acmicpc.net/problem/19237) (삼성): [Python 3.7 코드](19/3.py)
 
 ### Part 4 부록
 
-#### 부록 A 파이썬 문법
+#### 부록 A 코딩 테스트를 위한 파이썬 문법
 
 * 자료형
-    * 숫자 자료형
+    * 수 자료형
         * 정수형
         * 실수형
-        * 숫자 자료형의 연산
+        * 수 자료형의 연산
     * 리스트 자료형
-        * 리스트 초기화
+        * 리스트 만들기
         * 리스트 인덱싱
         * 리스트 슬라이싱
         * 리스트 컴프리헨션
@@ -202,10 +266,10 @@
         * 문자열 연산
     * 튜플 자료형
         * 튜플 초기화
-    * 딕셔너리 자료형
-        * 딕셔너리 초기화
-        * 딕셔너리에서 키로 검색
-        * 딕셔너리 관련 메서드
+    * 사전 자료형
+        * 사전 자료형 초기화
+        * 사전에서 키로 검색
+        * 사전 자료형 관련 메서드
     * 집합 자료형
         * 집합 초기화
         * 집합 연산
@@ -233,19 +297,54 @@
     * 코딩 테스트에서 입력을 위한 전형적인 코드
     * 공백을 기준으로 적은 수의 데이터 입력
     * readline()으로 빠르게 입력 받기
+    * f-string 사용 예시
+* 주요 라이브러리의 문법과 유의점
+    * 내장 함수
+    * itertools
+    * heapq
+    * bisect
+    * collections
+    * math
+* 자신만의 알고리즘 노트 만들기
 
 #### 부록 B 기타 알고리즘
 
 * 이론
-    * 소수 판별: Python 3.7 코드
-    * 에라토스테네스의 체: Python 3.7 코드
-    * 특정한 합을 가지는 부분 연속 수열 찾기 (투 포인터): Python 3.7 코드
-    * 정렬되어 있는 두 리스트 합치기 (투 포인터): Python 3.7 코드
-    * 구간 합: Python 3.7 코드
-    * 순열: Python 3.7 코드
-    * 조합: Python 3.7 코드
+    * 소수 판별: ([Python 3.7 코드](/20/1.py) / [C++ 코드](/20/1.cpp) / [Java 코드](/20/1.java))
+    * 에라토스테네스의 체: ([Python 3.7 코드](/20/2.py) / [C++ 코드](/20/2.cpp) / [Java 코드](/20/2.java))
+    * 특정한 합을 가지는 부분 연속 수열 찾기 (투 포인터): ([Python 3.7 코드](/20/3.py) / [C++ 코드](/20/3.cpp) / [Java 코드](/20/3.java))
+    * 정렬되어 있는 두 리스트 합치기 (투 포인터): [Python 3.7 코드](/20/4.py)
+    * 구간 합: ([Python 3.7 코드](/20/5.py) / [C++ 코드](/20/5.cpp) / [Java 코드](/20/5.java))
+    * 순열: [Python 3.7 코드](/20/6.py)
+    * 조합: [Python 3.7 코드](/20/7.py)
 * 실전
-    * 소수 구하기: Python 3.7 코드
-    * 암호 만들기: Python 3.7 코드
-
-#### 부록 C 코딩 테스트 유형 분석
+    * [소수 구하기](https://www.acmicpc.net/problem/1929) (핵심 유형): [Python 3.7 코드](/20/8.py)
+    * [암호 만들기](https://www.acmicpc.net/problem/1759) (핵심 유형): [Python 3.7 코드](/20/9.py)
+
+#### 부록 C 개발형 코딩 테스트
+
+* 서버와 클라이언트
+* REST API
+* JSON
+* API 호출 실습
+   * API 호출 실습 1
+   * API 호출 실습 2
+   * 회원 정보 처리 실습
+
+#### 부록 D 알고리즘 유형별 문제 풀이
+
+### 추가 보충 자료
+
+> 책에서는 자세히 다루지 않지만 독자의 요청으로 추가적으로 제공합니다.
+
+* 트리(Tree)
+  * 트리의 순회: ([Python 3.7 코드](/21/1.py))
+* 우선순위 큐 (Priority Queue)
+  * [우선순위 큐 라이브러리를 활용한 힙 정렬](https://www.acmicpc.net/problem/2751): ([Python 3.7 코드](/21/2.py) / [C++ 코드](/21/2.cpp))
+* 바이너리 인덱스 트리 (Binary Indexed Tree, BIT, Fenwick Tree)
+  * [구간 합 구하기](https://www.acmicpc.net/problem/2042): ([Python 3.7 코드](/21/3.py) / [C++ 코드](/21/3.cpp))
+* 벨만-포드 (Bellman-Ford) 최단 경로 알고리즘
+  * [음수 간선이 포함된 그래프에서의 최단 경로 찾기](https://www.acmicpc.net/problem/11657): ([Python 3.7 코드](/21/4.py) / [C++ 코드](/21/4.cpp))
+* 최소 공통 조상 (Lowest Common Ancestor, LCA)
+  * [LCA 기본](https://www.acmicpc.net/problem/11437): ([Python 3.7 코드](/21/5.py) / [C++ 코드](/21/5.cpp))
+  * [LCA 심화](https://www.acmicpc.net/problem/11438): ([Python 3.7 코드](/21/6.py) / [C++ 코드](/21/6.cpp))
diff --git a/notice.md b/notice.md
new file mode 100644
index 0000000..68a47a4
--- /dev/null
+++ b/notice.md
@@ -0,0 +1,95 @@
+## 정오표
+
+> 출판 전에 최대한 많은 검토 과정을 거쳤으나, 여전히 책에 존재하는 오류로 인해 불편함을 드려 정말 죄송합니다.
+
+### 초판 1쇄
+
+#### (118p) '게임 개발' 문제의 입력 조건 오류
+
+* 맵의 세로 크기 N과 가로 크기 M의 입력 범위는 (3 ≤ N, M ≤ 50)입니다.
+
+#### (143p) BFS 원어 오탈자
+
+* BFS는 Breadth First Search의 약자인데, 책에 d가 빠져 기재되어 있습니다.
+
+#### (190p) 이진 탐색 소스코드 주석 오류
+
+* 주석에서 "# 중간점의 값보다 찾고자 하는 값이 <b>큰</b> 경우 오른쪽 확인"이 올바른 내용입니다.
+
+#### (197p) '부품 찾기' 문제의 입력 조건 및 소스코드 오류
+
+* 문제의 조건에서 N개의 정수와 M개의 정수 모두 크기는 1보다 크고 1,000,000이하입니다.
+* '계수 정렬'을 이용한 답안에서 array 리스트 변수의 크기는 1,000,001입니다.
+
+#### (221p) 그림 내 오탈자
+
+* 그림 ⓑ에서 그림의 오른쪽 부분은 '털 수 있음'인데 잘못 기재되어 있습니다.
+
+#### (226p) 출력 조건 오탈자
+
+* 출력 조건으로 "첫째 줄에 M 원을 만들기 위한 <b>최소한의 화폐 개수를 출력</b>한다."가 올바른 내용입니다.
+
+#### (263p) 주석 오탈자
+
+* 주석에서 "# <b>x</b>번 노드에서 <b>y</b>번 노드로 가는 비용이 <b>z</b>라는 의미"가 올바른 내용입니다.
+
+#### (298p) '팀 결성' 문제의 입력 조건 오류
+
+* N과 M의 입력 범위는 (1 ≤ N, M ≤ 100,000)입니다.
+
+#### (368p) '고정점 찾기' 문제 설명 누락
+
+* 고정점은 최대 1개만 존재합니다.
+
+#### (423p) 두 번째 예제와 세 번째 예제 실행 결과 오류
+
+* 두 번째 예제와 세 번째 예제의 실행 결과가 잘못 기재되어 있습니다. 올바른 실행 결과는 다음과 같습니다.
+```
+# 두 번째 예제
+[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
+
+# 세 번째 예제
+[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
+[[0, 5, 0, 0], [0, 5, 0, 0], [0, 5, 0, 0]]
+```
+
+#### (455p) 두 번째 예시 본문 단어 표기 오류
+
+* 두 번째 예시는 최대 힙을 구현하여 <b>내림차순</b> 힙 정렬을 구현하는 예시입니다.
+
+#### (483p) 세 번째 쿼리 설명 오류
+
+* 세 번째 쿼리는 세 번째 수부터 <b>네 번째 수</b>까지의 구간 합을 물어보는 [3, 4]입니다. 
+
+### 초판 2쇄
+
+#### (255p) 수식 오탈자
+
+* 수식에서 "D12 + <b>D23</b> = 11과 비교해서 11로 갱신된다."가 올바른 내용입니다.
+
+#### (514p) 풀이 설명 오류
+
+* <b>\[Step 2\]</b>의 내용은 다음과 같이 변경되어야 올바른 내용입니다.
+> 전체 남은 시간은 3초이고, 이번 단계에서는 2번 음식을 빼야 한다. 전체 음식이 2개 남아 있으므로 이번 단계에서 뺄 시간은 2(남은 음식의 개수) X <b>2(2번 음식을 다 먹는 시간)</b> = <b>4</b>초가 된다. 하지만 현재 전체 남은 시간이 3초인데, 이는 <b>4</b>보다 작으므로 빼지 않도록 한다.
+
+#### (570p) 예시 설명
+
+* 문제 해설의 예시 설명에 오류가 있습니다. 올바른 설명은 [수정 사항이 반영된 설명 링크](https://github.com/ndb796/python-for-coding-test/blob/master/16/5_notice.md)와 같습니다.
+
+### 초판 3쇄
+
+#### (369p) '공유기 설치' 문제의 모범답안 오류
+
+* 모범답안의 start 변수를 초기화하는 부분에서 다음의 코드가 올바른 내용입니다.
+```
+start = 1 # 가능한 최소 거리(min gap)
+end = array[-1] - array[0] # 가능한 최대 거리(max gap)
+```
+
+#### (375p) '금광' 문제의 입력 조건 오류
+
+* 각 위치에 매장된 금의 개수는 1 이상이 아닌 <b>0 이상</b>입니다.
+
+#### (398p) 문제 내용 오탈자
+
+* 문제 설명에서 두 행성 A와 B를 터널로 연결할 때 드는 비용으로는 min(|xA-xB|, |yA-<b>yB</b>|, |zA-zB|)가 올바른 내용입니다.
