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 + +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/1.py b/10/1.py index 05342d8..41ed2f0 100644 --- a/10/1.py +++ b/10/1.py @@ -16,7 +16,7 @@ def union_parent(parent, a, b): # 노드의 개수와 간선(Union 연산)의 개수 입력 받기 v, e = map(int, input().split()) -parent = {} +parent = [0] * (v + 1) # 부모 테이블 초기화하기 # 부모 테이블상에서, 부모를 자기 자신으로 초기화 for i in range(1, v + 1): diff --git a/10/2.py b/10/2.py index 81f5a2c..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 = {} - -# 부모 테이블상에서, 부모를 자기 자신으로 초기화 -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 + +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 7a9e65a..d074ff6 100644 --- a/10/3.py +++ b/10/3.py @@ -2,7 +2,7 @@ def find_parent(parent, x): # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출 if parent[x] != x: - parent[x] = find_parent(parent, parent[x]) + parent[x] = find_parent(parent, parent[x]) return parent[x] # 두 원소가 속한 집합을 합치기 @@ -16,24 +16,25 @@ def union_parent(parent, a, b): # 노드의 개수와 간선(Union 연산)의 개수 입력 받기 v, e = map(int, input().split()) -parent = {} +parent = [0] * (v + 1) # 부모 테이블 초기화하기 # 부모 테이블상에서, 부모를 자기 자신으로 초기화 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 - 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 + +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 3b871fa..29a59ed 100644 --- a/10/4.py +++ b/10/4.py @@ -16,31 +16,25 @@ def union_parent(parent, a, b): # 노드의 개수와 간선(Union 연산)의 개수 입력 받기 v, e = map(int, input().split()) -parent = {} - -# 모든 간선을 담을 리스트와, 최종 비용을 담을 변수 -edges = [] -result = 0 +parent = [0] * (v + 1) # 부모 테이블 초기화하기 # 부모 테이블상에서, 부모를 자기 자신으로 초기화 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 + +using namespace std; + +// 노드의 개수(V)와 간선(Union 연산)의 개수(E) +// 노드의 개수는 최대 100,000개라고 가정 +int v, e; +int parent[100001]; // 부모 테이블 초기화 +// 모든 간선을 담을 리스트와, 최종 비용을 담을 변수 +vector > > 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 { + + 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 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 + +using namespace std; + +// 노드의 개수(V)와 간선의 개수(E) +// 노드의 개수는 최대 100,000개라고 가정 +int v, e; +// 모든 노드에 대한 진입차수는 0으로 초기화 +int indegree[100001]; +// 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화 +vector graph[100001]; + +// 위상 정렬 함수 +void topologySort() { + vector result; // 알고리즘 수행 결과를 담을 리스트 + queue 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> graph = new ArrayList>(); + + // 위상 정렬 함수 + public static void topologySort() { + ArrayList result = new ArrayList<>(); // 알고리즘 수행 결과를 담을 리스트 + Queue 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()); + } + + // 방향 그래프의 모든 간선 정보를 입력 받기 + 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 33e9dbc..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 = {} +# 방향 그래프의 모든 간선 정보를 입력 받기 +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 + +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 d1660e6..d03509f 100644 --- a/10/7.py +++ b/10/7.py @@ -2,7 +2,7 @@ def find_parent(parent, x): # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출 if parent[x] != x: - parent[x] = find_parent(parent, parent[x]) + parent[x] = find_parent(parent, parent[x]) return parent[x] # 두 원소가 속한 집합을 합치기 @@ -14,35 +14,22 @@ def union_parent(parent, a, b): else: parent[a] = b -# 노드의 개수와 간선(Union 연산)의 개수 입력 받기 -v, e = map(int, input().split()) -parent = {} - -# 모든 간선을 담을 리스트와, 최종 비용을 담을 변수 -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 + +using namespace std; + +// 노드의 개수와 간선(Union 연산)의 개수 입력받기 +int v, e; +int parent[100001]; // 부모 테이블 초기화 +// 모든 간선을 담을 리스트와, 최종 비용을 담을 변수 +vector > > 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 { + + 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 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 edb6aa0..f709693 100644 --- a/10/8.py +++ b/10/8.py @@ -1,46 +1,48 @@ -from collections import deque -import copy - -# 노드의 개수 입력 받기 -v = int(input()) -# 모든 노드에 대한 진입차수는 0으로 초기화 -indegree = [0] * (v + 1) -# 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화 -adj = [[] 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 - adj[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 adj[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 + +using namespace std; + +// 노드의 개수(V) +int v; +// 모든 노드에 대한 진입차수는 0으로 초기화 +int indegree[501]; +// 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화 +vector graph[501]; +// 각 강의 시간을 0으로 초기화 +int times[501]; + +// 위상 정렬 함수 +void topologySort() { + vector result(501); // 알고리즘 수행 결과를 담을 리스트 + for (int i = 1; i <= v; i++) { + result[i] = times[i]; + } + + queue 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> graph = new ArrayList>(); + // 각 강의 시간을 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 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()); + } + + // 방향 그래프의 모든 간선 정보를 입력받기 + 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 + +using namespace std; + +int n; +vector 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 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/1.py b/11/1.py new file mode 100644 index 0000000..039430d --- /dev/null +++ b/11/1.py @@ -0,0 +1,14 @@ +n = int(input()) +data = list(map(int, input().split())) +data.sort() + +result = 0 # 총 그룹의 수 +count = 0 # 현재 그룹에 포함된 모험가의 수 + +for i in data: # 공포도를 낮은 것부터 하나씩 확인하며 + count += 1 # 현재 그룹에 해당 모험가를 포함시키기 + if count >= i: # 현재 그룹에 포함된 모험가의 수가 현재의 공포도 이상이라면, 그룹 결성 + result += 1 # 총 그룹의 수 증가시키기 + count = 0 # 현재 그룹에 포함된 모험가의 수 초기화 + +print(result) # 총 그룹의 수 출력 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 + +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 new file mode 100644 index 0000000..f6e6294 --- /dev/null +++ b/11/2.py @@ -0,0 +1,14 @@ +data = input() + +# 첫 번째 문자를 숫자로 변경하여 대입 +result = int(data[0]) + +for i in range(1, len(data)): + # 두 수 중에서 하나라도 '0' 혹은 '1'인 경우, 곱하기보다는 더하기 수행 + num = int(data[i]) + if num <= 1 or result <= 1: + result += num + else: + 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 + +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/3.py b/11/3.py new file mode 100644 index 0000000..6c2a075 --- /dev/null +++ b/11/3.py @@ -0,0 +1,21 @@ +data = input() +count0 = 0 # 전부 0으로 바꾸는 경우 +count1 = 0 # 전부 1로 바꾸는 경우 + +# 첫 번째 원소에 대해서 처리 +if data[0] == '1': + count0 += 1 +else: + count1 += 1 + +# 두 번째 원소부터 모든 원소를 확인하며 +for i in range(len(data) - 1): + if data[i] != data[i + 1]: + # 다음 수에서 1로 바뀌는 경우 + if data[i + 1] == '1': + count0 += 1 + # 다음 수에서 0으로 바뀌는 경우 + else: + count1 += 1 + +print(min(count0, count1)) 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 + +using namespace std; + +int n; +vector 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 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/4.py b/11/4.py new file mode 100644 index 0000000..2dab0d4 --- /dev/null +++ b/11/4.py @@ -0,0 +1,13 @@ +n = int(input()) +data = list(map(int, input().split())) +data.sort() + +target = 1 +for x in data: + # 만들 수 없는 금액을 찾았을 때 반복 종료 + if target < x: + break + target += x + +# 만들 수 없는 금액 출력 +print(target) 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 + +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/5.py b/11/5.py new file mode 100644 index 0000000..76ca231 --- /dev/null +++ b/11/5.py @@ -0,0 +1,17 @@ +n, m = map(int, input().split()) +data = list(map(int, input().split())) + +# 1부터 10까지의 무게를 담을 수 있는 리스트 +array = [0] * 11 + +for x in data: + # 각 무게에 해당하는 볼링공의 개수 카운트 + array[x] += 1 + +result = 0 +# 1부터 m까지의 각 무게에 대하여 처리 +for i in range(1, m + 1): + n -= array[i] # 무게가 i인 볼링공의 개수(A가 선택할 수 있는 개수) 제외 + result += array[i] * n # B가 선택하는 경우의 수와 곱해주기 + +print(result) 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 + +using namespace std; + +bool compare(pair a, pair b) { + return a.second < b.second; +} + +int solution(vector 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 > 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 > 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 { + + 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 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 result = new ArrayList<>(); + while (!pq.isEmpty()) { + result.add(pq.poll()); + } + // 음식의 번호 기준으로 정렬 + Collections.sort(result, new Comparator() { + @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 new file mode 100644 index 0000000..3f339d7 --- /dev/null +++ b/11/6.py @@ -0,0 +1,27 @@ +import heapq + +def solution(food_times, k): + # 전체 음식을 먹는 시간보다 k가 크거나 같다면 -1 + if sum(food_times) <= k: + return -1 + + # 시간이 작은 음식부터 빼야 하므로 우선순위 큐를 이용 + q = [] + for i in range(len(food_times)): + # (음식 시간, 음식 번호) 형태로 우선순위 큐에 삽입 + heapq.heappush(q, (food_times[i], i + 1)) + + sum_value = 0 # 먹기 위해 사용한 시간 + previous = 0 # 직전에 다 먹은 음식 시간 + length = len(food_times) # 남은 음식의 개수 + + # sum_value + (현재의 음식 시간 - 이전 음식 시간) * 현재 음식 개수와 k 비교 + while sum_value + ((q[0][0] - previous) * length) <= k: + now = heapq.heappop(q)[0] + sum_value += (now - previous) * length + length -= 1 # 다 먹은 음식 제외 + previous = now # 이전 음식 시간 재설정 + + # 남은 음식 중에서 몇 번째 음식인지 확인하여 출력 + 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 + +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/1.py b/12/1.py new file mode 100644 index 0000000..dd5c37f --- /dev/null +++ b/12/1.py @@ -0,0 +1,17 @@ +n = input() +length = len(n) # 점수 값의 총 자릿수 +summary = 0 + +# 왼쪽 부분의 자릿수의 합 더하기 +for i in range(length // 2): + summary += int(n[i]) + +# 오른쪽 부분의 자릿수의 합 빼기 +for i in range(length // 2, length): + summary -= int(n[i]) + +# 왼쪽 부분과 오른쪽 부분의 자릿수 합이 동일한지 검사 +if summary == 0: + print("LUCKY") +else: + print("READY") 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 + +using namespace std; + +string str; +vector 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 result = new ArrayList(); + 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 new file mode 100644 index 0000000..9e9935f --- /dev/null +++ b/12/2.py @@ -0,0 +1,22 @@ +data = input() +result = [] +value = 0 + +# 문자를 하나씩 확인하며 +for x in data: + # 알파벳인 경우 결과 리스트에 삽입 + if x.isalpha(): + result.append(x) + # 숫자는 따로 더하기 + else: + value += int(x) + +# 알파벳을 오름차순으로 정렬 +result.sort() + +# 숫자가 하나라도 존재하는 경우 가장 뒤에 삽입 +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 + +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 new file mode 100644 index 0000000..94d712b --- /dev/null +++ b/12/3.py @@ -0,0 +1,22 @@ +def solution(s): + answer = len(s) + # 1개 단위(step)부터 압축 단위를 늘려가며 확인 + for step in range(1, len(s) // 2 + 1): + compressed = "" + prev = s[0:step] # 앞에서부터 step만큼의 문자열 추출 + count = 1 + # 단위(step) 크기만큼 증가시키며 이전 문자열과 비교 + for j in range(step, len(s), step): + # 이전 상태와 동일하다면 압축 횟수(count) 증가 + if prev == s[j:j + step]: + count += 1 + # 다른 문자열이 나왔다면(더 이상 압축하지 못하는 경우라면) + else: + compressed += str(count) + prev if count >= 2 else prev + prev = s[j:j + step] # 다시 상태 초기화 + count = 1 + # 남아있는 문자열에 대해서 처리 + compressed += str(count) + prev if count >= 2 else prev + # 만들어지는 압축 문자열이 가장 짧은 것이 정답 + answer = min(answer, len(compressed)) + return answer 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 + +using namespace std; + +// 2차원 리스트 90도 회전하기 +vector > rotateMatrixBy90Degree(vector > a) { + int n = a.size(); // 행 길이 계산 + int m = a[0].size(); // 열 길이 계산 + vector > result(n, vector(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 > 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 > key, vector > lock) { + int n = lock.size(); + int m = key.size(); + // 자물쇠의 크기를 기존의 3배로 변환 + vector > newLock(n * 3, vector(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 new file mode 100644 index 0000000..4ecbaf1 --- /dev/null +++ b/12/4.py @@ -0,0 +1,46 @@ +# 2차원 리스트 90도 회전하기 +def rotate_a_matrix_by_90_degree(a): + n = len(a) # 행 길이 계산 + m = len(a[0]) # 열 길이 계산 + result = [[0] * n for _ in range(m)] # 결과 리스트 + for i in range(n): + for j in range(m): + result[j][n - i - 1] = a[i][j] + return result + +# 자물쇠의 중간 부분이 모두 1인지 확인 +def check(new_lock): + lock_length = len(new_lock) // 3 + for i in range(lock_length, lock_length * 2): + for j in range(lock_length, lock_length * 2): + if new_lock[i][j] != 1: + return False + return True + +def solution(key, lock): + n = len(lock) + m = len(key) + # 자물쇠의 크기를 기존의 3배로 변환 + new_lock = [[0] * (n * 3) for _ in range(n * 3)] + # 새로운 자물쇠의 중앙 부분에 기존의 자물쇠 넣기 + for i in range(n): + for j in range(n): + new_lock[i + n][j + n] = lock[i][j] + + # 4가지 방향에 대해서 확인 + for rotation in range(4): + 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] + return False 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 + +using namespace std; + +int n, k, l; +int arr[101][101]; // 맵 정보 +vector > 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 > 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 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 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 new file mode 100644 index 0000000..e148ca1 --- /dev/null +++ b/12/5.py @@ -0,0 +1,62 @@ +n = int(input()) +k = int(input()) +data = [[0] * (n + 1) for _ in range(n + 1)] # 맵 정보 +info = [] # 방향 회전 정보 + +# 맵 정보(사과 있는 곳은 1로 표시) +for _ in range(k): + a, b = map(int, input().split()) + data[a][b] = 1 + +# 방향 회전 정보 입력 +l = int(input()) +for _ in range(l): + x, c = input().split() + info.append((int(x), c)) + +# 처음에는 오른쪽을 보고 있으므로(동, 남, 서, 북) +dx = [0, 1, 0, -1] +dy = [1, 0, -1, 0] + +def turn(direction, c): + if c == "L": + direction = (direction - 1) % 4 + else: + direction = (direction + 1) % 4 + return direction + +def simulate(): + x, y = 1, 1 # 뱀의 머리 위치 + data[x][y] = 2 # 뱀이 존재하는 위치는 2로 표시 + direction = 0 # 처음에는 동쪽을 보고 있음 + time = 0 # 시작한 뒤에 지난 '초' 시간 + index = 0 # 다음에 회전할 정보 + q = [(x, y)] # 뱀이 차지하고 있는 위치 정보(꼬리가 앞쪽) + + while True: + nx = x + dx[direction] + ny = y + dy[direction] + # 맵 범위 안에 있고, 뱀의 몸통이 없는 위치라면 + if 1 <= nx and nx <= n and 1 <= ny and ny <= n and data[nx][ny] != 2: + # 사과가 없다면 이동 후에 꼬리 제거 + if data[nx][ny] == 0: + data[nx][ny] = 2 + q.append((nx, ny)) + px, py = q.pop(0) + data[px][py] = 0 + # 사과가 있다면 이동 후에 꼬리 그대로 두기 + if data[nx][ny] == 1: + data[nx][ny] = 2 + q.append((nx, ny)) + # 벽이나 뱀의 몸통과 부딪혔다면 + else: + time += 1 + break + x, y = nx, ny # 다음 위치로 머리를 이동 + time += 1 + if index < l and time == info[index][0]: # 회전할 시간인 경우 회전 + direction = turn(direction, info[index][1]) + index += 1 + return time + +print(simulate()) 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 + +using namespace std; + +// 현재 설치된 구조물이 '가능한' 구조물인지 확인하는 함수 +bool possible(vector > 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 > solution(int n, vector > build_frame) { + vector > 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 erased = answer[index]; + answer.erase(answer.begin() + index); + if (!possible(answer)) { // 가능한 구조물인지 확인 + answer.push_back(erased); // 가능한 구조물이 아니라면 다시 설치 + } + } + if (operate == 1) { // 설치하는 경우 + // 일단 설치를 해 본 뒤에 + vector 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 { + + 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> 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> answer = new ArrayList>(); + // 작업(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 erased = answer.get(index); + answer.remove(index); + if (!possible(answer)) { // 가능한 구조물인지 확인 + answer.add(erased); // 가능한 구조물이 아니라면 다시 설치 + } + } + if (operate == 1) { // 설치하는 경우 + // 일단 설치를 해 본 뒤에 + ArrayList inserted = new ArrayList(); + inserted.add(x); + inserted.add(y); + inserted.add(stuff); + answer.add(inserted); + if (!possible(answer)) { // 가능한 구조물인지 확인 + answer.remove(answer.size() - 1); // 가능한 구조물이 아니라면 다시 제거 + } + } + } + + // 정렬 수행 + ArrayList ans = new ArrayList(); + 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 new file mode 100644 index 0000000..d05e3f2 --- /dev/null +++ b/12/6.py @@ -0,0 +1,28 @@ +# 현재 설치된 구조물이 '가능한' 구조물인지 확인하는 함수 +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) 반환 + return True + +def solution(n, build_frame): + answer = [] + for frame in build_frame: # 작업(frame)의 개수는 최대 1,000개 + x, y, stuff, operate = frame + if operate == 0: # 삭제하는 경우 + answer.remove([x, y, stuff]) # 일단 삭제를 해본 뒤에 + if not possible(answer): # 가능한 구조물인지 확인 + answer.append([x, y, stuff]) # 가능한 구조물이 아니라면 다시 설치 + if operate == 1: # 설치하는 경우 + 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 + +using namespace std; + +int n, m; +int arr[50][50]; +vector > chicken; +vector > house; + +// 치킨 거리의 합을 계산하는 함수 +int getSum(vector > 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 binary(chicken.size()); + fill(binary.end() - m, binary.end(), true); + + // 치킨 거리의 합의 최소를 찾아 출력 + int result = 1e9; + + do { + vector > 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> result; // 모든 조합 + + public ArrayList> getResult() { + return result; + } + + public Combination(int n, int r) { + this.n = n; + this.r = r; + this.now = new int[r]; + this.result = new ArrayList>(); + } + + public void combination(ArrayList arr, int depth, int index, int target) { + if (depth == r) { + ArrayList 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 chicken = new ArrayList<>(); + public static ArrayList house = new ArrayList<>(); + + public static int getSum(ArrayList 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> 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 new file mode 100644 index 0000000..7c29b91 --- /dev/null +++ b/12/7.py @@ -0,0 +1,36 @@ +from itertools import combinations + +n, m = map(int, input().split()) +chicken, house = [], [] + +for r in range(n): + data = list(map(int, input().split())) + for c in range(n): + if data[c] == 1: + house.append((r, c)) # 일반 집 + elif data[c] == 2: + chicken.append((r, c)) # 치킨집 + +# 모든 치킨 집 중에서 m개의 치킨 집을 뽑는 조합 계산 +candidates = list(combinations(chicken, m)) + +# 치킨 거리의 합을 계산하는 함수 +def get_sum(candidate): + result = 0 + # 모든 집에 대하여 + for hx, hy in house: + # 가장 가까운 치킨 집을 찾기 + temp = 1e9 + for cx, cy in candidate: + temp = min(temp, abs(hx - cx) + abs(hy - cy)) + # 가장 가까운 치킨 집까지의 거리를 더하기 + result += temp + # 치킨 거리의 합 반환 + return result + +# 치킨 거리의 합의 최소를 찾아 출력 +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 + +using namespace std; + +int solution(int n, vector weak, vector 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> result; // 모든 순열 + + public ArrayList> getResult() { + return result; + } + + public Permutation(int n, int r) { + this.n = n; + this.r = r; + this.now = new int[r]; + this.result = new ArrayList>(); + } + + 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 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 weakList = new ArrayList(); + 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> 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 new file mode 100644 index 0000000..ae408bd --- /dev/null +++ b/12/8.py @@ -0,0 +1,27 @@ +from itertools import permutations + +def solution(n, weak, dist): + # 길이를 2배로 늘려서 '원형'을 일자 형태로 변형 + length = len(weak) + for i in range(length): + weak.append(weak[i] + n) + answer = len(dist) + 1 # 투입할 친구 수의 최솟값을 찾아야 하므로 len(dist) + 1로 초기화 + # 0부터 length - 1까지의 위치를 각각 시작점으로 설정 + for start in range(length): + # 친구를 나열하는 모든 경우 각각에 대하여 확인 + for friends in list(permutations(dist, len(dist))): + count = 1 # 투입할 친구의 수 + # 해당 친구가 점검할 수 있는 마지막 위치 + position = weak[start] + friends[count - 1] + # 시작점부터 모든 취약한 지점을 확인 + for index in range(start, start + length): + # 점검할 수 있는 위치를 벗어나는 경우 + if position < weak[index]: + count += 1 # 새로운 친구를 투입 + if count > len(dist): # 더 투입이 불가능하다면 종료 + break + position = weak[index] + friends[count - 1] + answer = min(answer, count) # 최솟값 계산 + if answer > len(dist): + return -1 + return answer 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 + +using namespace std; + +// 도시의 개수, 도로의 개수, 거리 정보, 출발 도시 번호 +int n, m, k, x; +vector graph[300001]; +// 모든 도시에 대한 최단 거리 초기화 +vector 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 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> graph = new ArrayList>(); + // 모든 도시에 대한 최단 거리 초기화 + 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()); + 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 q = new LinkedList(); + 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 new file mode 100644 index 0000000..ad11e2b --- /dev/null +++ b/13/1.py @@ -0,0 +1,37 @@ +from collections import deque + +# 도시의 개수, 도로의 개수, 거리 정보, 출발 도시 번호 +n, m, k, x = map(int, input().split()) +graph = [[] for _ in range(n + 1)] + +# 모든 도로 정보 입력 받기 +for _ in range(m): + a, b = map(int, input().split()) + graph[a].append(b) + +# 모든 도시에 대한 최단 거리 초기화 +distance = [-1] * (n + 1) +distance[x] = 0 # 출발 도시까지의 거리는 0으로 설정 + +# 너비 우선 탐색(BFS) 수행 +q = deque([x]) +while q: + now = q.popleft() + # 현재 도시에서 이동할 수 있는 모든 도시를 확인 + for next_node in graph[now]: + # 아직 방문하지 않은 도시라면 + if distance[next_node] == -1: + # 최단 거리 갱신 + distance[next_node] = distance[now] + 1 + q.append(next_node) + +# 최단 거리가 K인 모든 도시의 번호를 오름차순으로 출력 +check = False +for i in range(1, n + 1): + if distance[i] == k: + print(i) + check = True + +# 만약 최단 거리가 K인 도시가 없다면, -1 출력 +if check == False: + print(-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 + +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 new file mode 100644 index 0000000..6ad7899 --- /dev/null +++ b/13/2.py @@ -0,0 +1,64 @@ +# BOJ에서는 [언어]를 PyPy3로 설정하여 제출해주세요. + +n, m = map(int, input().split()) +data = [] # 초기 맵 리스트 +temp = [[0] * m for _ in range(n)] # 벽을 설치한 뒤의 맵 리스트 + +for _ in range(n): + data.append(list(map(int, input().split()))) + +# 4가지 이동 방향에 대한 리스트 +dx = [-1, 0, 1, 0] +dy = [0, 1, 0, -1] + +result = 0 + +# 깊이 우선 탐색(DFS)을 이용해 각 바이러스가 사방으로 퍼지도록 하기 +def virus(x, y): + for i in range(4): + nx = x + dx[i] + ny = y + dy[i] + # 상, 하, 좌, 우 중에서 바이러스가 퍼질 수 있는 경우 + if nx >= 0 and nx < n and ny >= 0 and ny < m: + if temp[nx][ny] == 0: + # 해당 위치에 바이러스 배치하고, 다시 재귀적으로 수행 + temp[nx][ny] = 2 + virus(nx, ny) + +# 현재 맵에서 안전 영역의 크기 계산하는 메서드 +def get_score(): + score = 0 + for i in range(n): + for j in range(m): + if temp[i][j] == 0: + score += 1 + return score + +# 깊이 우선 탐색(DFS)을 이용해 울타리를 설치하면서, 매 번 안전 영역의 크기 계산 +def dfs(count): + global result + # 울타리가 3개 설치된 경우 + if count == 3: + for i in range(n): + for j in range(m): + temp[i][j] = data[i][j] + # 각 바이러스의 위치에서 전파 진행 + for i in range(n): + for j in range(m): + if temp[i][j] == 2: + virus(i, j) + # 안전 영역의 최대값 계산 + result = max(result, get_score()) + return + # 빈 공간에 울타리를 설치 + for i in range(n): + for j in range(m): + if data[i][j] == 0: + data[i][j] = 1 + count += 1 + dfs(count) + data[i][j] = 0 + count -= 1 + +dfs(0) +print(result) 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 + +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 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 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 { + + 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 viruses = new ArrayList(); + + // 바이러스가 퍼져나갈 수 있는 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 q = new LinkedList(); + 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 new file mode 100644 index 0000000..c21d0f2 --- /dev/null +++ b/13/3.py @@ -0,0 +1,44 @@ +from collections import deque + +n, k = map(int, input().split()) + +graph = [] # 전체 보드 정보를 담는 리스트 +data = [] # 바이러스에 대한 정보를 담는 리스트 + +for i in range(n): + # 보드 정보를 한 줄 단위로 입력 + graph.append(list(map(int, input().split()))) + for j in range(n): + # 해당 위치에 바이러스가 존재하는 경우 + if graph[i][j] != 0: + # (바이러스 종류, 시간, 위치 X, 위치 Y) 삽입 + data.append((graph[i][j], 0, i, j)) + +# 정렬 이후에 큐로 옮기기 (낮은 번호의 바이러스가 먼저 증식하므로) +data.sort() +q = deque(data) + +target_s, target_x, target_y = map(int, input().split()) + +# 바이러스가 퍼져나갈 수 있는 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가지 위치를 각각 확인 + 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 graph[nx][ny] == 0: + graph[nx][ny] = virus + q.append((virus, s + 1, nx, ny)) + +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 + +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 new file mode 100644 index 0000000..a1e448a --- /dev/null +++ b/13/4.py @@ -0,0 +1,46 @@ +# "균형잡힌 괄호 문자열"의 인덱스 반환 +def balanced_index(p): + count = 0 # 왼쪽 괄호의 개수 + for i in range(len(p)): + if p[i] == '(': + count += 1 + else: + count -= 1 + if count == 0: + return i + +# "올바른 괄호 문자열"인지 판단 +def check_proper(p): + count = 0 # 왼쪽 괄호의 개수 + for i in p: + if i == '(': + count += 1 + else: + if count == 0: # 쌍이 맞지 않는 경우에 False 반환 + return False + count -= 1 + return True # 쌍이 맞는 경우에 True 반환 + +def solution(p): + answer = '' + if p == '': + return answer + index = balanced_index(p) + u = p[:index + 1] + v = p[index + 1:] + # "올바른 괄호 문자열"이면, v에 대해 함수를 수행한 결과를 붙여 반환 + if check_proper(u): + answer = u + solution(v) + # "올바른 괄호 문자열"이 아니라면 아래의 과정을 수행 + else: + answer = '(' + answer += solution(v) + answer += ')' + u = list(u[1:-1]) # 첫 번째와 마지막 문자를 제거 + for i in range(len(u)): + if u[i] == '(': + u[i] = ')' + else: + u[i] = '(' + answer += "".join(u) + return 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 + +using namespace std; + +int n; +// 연산을 수행하고자 하는 수 리스트 +vector 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 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 new file mode 100644 index 0000000..1cedfe4 --- /dev/null +++ b/13/5.py @@ -0,0 +1,42 @@ +n = int(input()) +# 연산을 수행하고자 하는 수 리스트 +data = list(map(int, input().split())) +# 더하기, 빼기, 곱하기, 나누기 연산자 개수 +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: + # 각 연산자에 대하여 재귀적으로 수행 + if add > 0: + add -= 1 + dfs(i + 1, now + data[i]) + add += 1 + if sub > 0: + sub -= 1 + dfs(i + 1, now - data[i]) + sub += 1 + if mul > 0: + mul -= 1 + dfs(i + 1, now * data[i]) + mul += 1 + if div > 0: + div -= 1 + 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 + +using namespace std; + +int n; // 복도의 크기 +char board[6][6]; // 복도 정보 (N x N) +vector > teachers; // 모든 선생님 위치 정보 +vector > 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 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> result; // 모든 조합 + + public ArrayList> getResult() { + return result; + } + + public Combination(int n, int r) { + this.n = n; + this.r = r; + this.now = new int[r]; + this.result = new ArrayList>(); + } + + public void combination(ArrayList arr, int depth, int index, int target) { + if (depth == r) { + ArrayList 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 teachers = new ArrayList<>(); // 모든 선생님 위치 정보 + public static ArrayList 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> 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 new file mode 100644 index 0000000..d09807d --- /dev/null +++ b/13/6.py @@ -0,0 +1,83 @@ +from itertools import combinations + +n = int(input()) # 복도의 크기 +board = [] # 복도 정보 (N x N) +teachers = [] # 모든 선생님 위치 정보 +spaces = [] # 모든 빈 공간 위치 정보 + +for i in range(n): + board.append(list(input().split())) + for j in range(n): + # 선생님이 존재하는 위치 저장 + if board[i][j] == 'T': + teachers.append((i, j)) + # 장애물을 설치할 수 있는 (빈 공간) 위치 저장 + if board[i][j] == 'X': + spaces.append((i, j)) + +# 특정 방향으로 감시를 진행 (학생 발견: True, 학생 미발견: False) +def watch(x, y, 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 + +# 장애물 설치 이후에, 한 명이라도 학생이 감지되는지 검사 +def process(): + # 모든 선생의 위치를 하나씩 확인 + for x, y in teachers: + # 4가지 방향으로 학생을 감지할 수 있는지 확인 + for i in range(4): + if watch(x, y, i): + return True + return False + +find = False # 학생이 한 명도 감지되지 않도록 설치할 수 있는지의 여부 + +# 빈 공간에서 3개를 뽑는 모든 조합을 확인 +for data in combinations(spaces, 3): + # 장애물들을 설치해보기 + for x, y in data: + board[x][y] = 'O' + # 학생이 한 명도 감지되지 않는 경우 + if not process(): + # 원하는 경우를 발견한 것임 + find = True + break + # 설치된 장애물을 다시 없애기 + for x, y in data: + board[x][y] = 'X' + +if find: + print('YES') +else: + print('NO') 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 + +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 > united; + united.push_back({x, y}); + // 너비 우선 탐색 (BFS)을 위한 큐 라이브러리 사용 + queue > 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 united = new ArrayList<>(); + united.add(new Position(x, y)); + // 너비 우선 탐색 (BFS)을 위한 큐 라이브러리 사용 + Queue 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 new file mode 100644 index 0000000..bf84ac7 --- /dev/null +++ b/13/7.py @@ -0,0 +1,63 @@ +from collections import deque + +# 땅의 크기(N), L, R 값을 입력받기 +n, l, r = map(int, input().split()) + +# 전체 나라의 정보(N x N)를 입력 받기 +graph = [] +for _ in range(n): + graph.append(list(map(int, input().split()))) + +dx = [-1, 0, 1, 0] +dy = [0, -1, 0, 1] + +# 특정 위치에서 출발하여 모든 연합을 체크한 뒤에 데이터 갱신 +def process(x, y, index): + # (x, y)의 위치와 연결된 나라(연합) 정보를 담는 리스트 + united = [] + united.append((x, y)) + # 너비 우선 탐색 (BFS)을 위한 큐 라이브러리 사용 + q = deque() + q.append((x, y)) + 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: + # 옆에 있는 나라와 인구 차이가 L명 이상, R명 이하라면 + if l <= abs(graph[nx][ny] - graph[x][y]) <= r: + q.append((nx, ny)) + # 연합에 추가하기 + union[nx][ny] = index + summary += graph[nx][ny] + count += 1 + united.append((nx, ny)) + # 연합 국가끼리 인구를 분배 + for i, j in united: + graph[i][j] = summary // count + +total_count = 0 + +# 더 이상 인구 이동을 할 수 없을 때까지 반복 +while True: + union = [[-1] * n for _ in range(n)] + index = 0 + for i in range(n): + for j in range(n): + 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 + +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 getNextPos(Node pos, vector > board) { + vector 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 > board) { + // 맵의 외곽에 벽을 두는 형태로 맵 변형 + int n = board.size(); + vector > newBoard(n + 2, vector(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 > q; + vector 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 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 getNextPos(Node pos, int[][] board) { + // 반환 결과(이동 가능한 위치들) + ArrayList nextPos = new ArrayList(); + // (상, 하, 좌, 우)로 이동하는 경우에 대해서 처리 + 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 q = new LinkedList<>(); + ArrayList 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 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 new file mode 100644 index 0000000..ec4cdb3 --- /dev/null +++ b/13/8.py @@ -0,0 +1,55 @@ +from collections import deque + +def get_next_pos(pos, board): + next_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)}) + # 현재 로봇이 가로로 놓여 있는 경우 + if pos1_x == pos2_x: + for i in [-1, 1]: # 위쪽으로 회전하거나, 아래쪽으로 회전 + if board[pos1_x + i][pos1_y] == 0 and board[pos2_x + i][pos2_y] == 0: # 위쪽 혹은 아래쪽 두 칸이 모두 비어 있다면 + next_pos.append({(pos1_x, pos1_y), (pos1_x + i, pos1_y)}) + next_pos.append({(pos2_x, pos2_y), (pos2_x + i, pos2_y)}) + # 현재 로봇이 세로로 놓여 있는 경우 + elif pos1_y == pos2_y: + for i in [-1, 1]: # 왼쪽으로 회전하거나, 오른쪽으로 회전 + if board[pos1_x][pos1_y + i] == 0 and board[pos2_x][pos2_y + i] == 0: # 왼쪽 혹은 오른쪽 두 칸이 모두 비어 있다면 + next_pos.append({(pos1_x, pos1_y), (pos1_x, pos1_y + i)}) + next_pos.append({(pos2_x, pos2_y), (pos2_x, pos2_y + i)}) + # 현재 위치에서 이동할 수 있는 위치를 반환 + return next_pos + +def solution(board): + # 맵의 외곽에 벽을 두는 형태로 맵 변형 + n = len(board) + new_board = [[1] * (n + 2) for _ in range(n + 2)] + for i in range(n): + for j in range(n): + new_board[i + 1][j + 1] = board[i][j] + # 너비 우선 탐색(BFS) 수행 + q = deque() + visited = [] + pos = {(1, 1), (1, 2)} # 시작 위치 설정 + q.append((pos, 0)) # 큐에 삽입한 뒤에 + visited.append(pos) # 방문 처리 + # 큐가 빌 때까지 반복 + while q: + pos, cost = q.popleft() + # (n, n) 위치에 로봇이 도달했다면, 최단 거리이므로 반환 + if (n, n) in pos: + return cost + # 현재 위치에서 이동할 수 있는 위치 확인 + for next_pos in get_next_pos(pos, new_board): + # 아직 방문하지 않은 위치라면 큐에 삽입하고 방문 처리 + if next_pos not in visited: + q.append((next_pos, cost + 1)) + visited.append(next_pos) + return 0 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 + +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 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 { + + 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 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 new file mode 100644 index 0000000..b8cb1f7 --- /dev/null +++ b/14/1.py @@ -0,0 +1,19 @@ +n = int(input()) +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 + +using namespace std; + +int n; +vector 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 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 new file mode 100644 index 0000000..7bb91cb --- /dev/null +++ b/14/2.py @@ -0,0 +1,6 @@ +n = int(input()) +a = list(map(int, input().split())) +a.sort() + +# 중간값(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 + +using namespace std; + +bool compare(pair a, pair b) { + if (a.second == b.second) return a.first < b.first; + return a.second > b.second; +} + +vector solution(int N, vector stages) { + vector > v; + vector 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 { + + 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 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 new file mode 100644 index 0000000..982b97b --- /dev/null +++ b/14/3.py @@ -0,0 +1,25 @@ +def solution(N, stages): + answer = [] + length = len(stages) + + # 스테이지 번호를 1부터 N까지 증가시키며 + for i in range(1, N + 1): + # 해당 스테이지에 머물러 있는 사람의 수 계산 + count = stages.count(i) + + # 실패율 계산 + if length == 0: + fail = 0 + 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 + +using namespace std; + +int n, result; +priority_queue 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 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 new file mode 100644 index 0000000..f98f199 --- /dev/null +++ b/14/4.py @@ -0,0 +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 + +using namespace std; + +// 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수 +int countByRange(vector& v, int leftValue, int rightValue) { + vector::iterator rightIndex = upper_bound(v.begin(), v.end(), rightValue); + vector::iterator leftIndex = lower_bound(v.begin(), v.end(), leftValue); + return rightIndex - leftIndex; +} + +int n, x; +vector 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 + +using namespace std; + +// 이진 탐색 소스코드 구현(재귀 함수) +int binarySearch(vector& 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 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 + +using namespace std; + +// 집의 개수(N)와 공유기의 개수(C) +int n, c; +vector 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 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 + +using namespace std; + +// 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수 +int countByRange(vector& v, string leftValue, string rightValue) { + vector::iterator rightIndex = upper_bound(v.begin(), v.end(), rightValue); + vector::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 arr[10001]; +// 모든 단어들을 길이마다 나누어서 뒤집어 저장하기 위한 리스트 +vector reversed_arr[10001]; + +vector solution(vector words, vector queries) { + vector 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 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 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 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> arr = new ArrayList>(); + // 모든 단어들을 길이마다 나누어서 뒤집어 저장하기 위한 리스트 + public ArrayList> reversedArr = new ArrayList>(); + + public int[] solution(String[] words, String[] queries) { + ArrayList ans = new ArrayList(); + + // 단어의 길이는 10,000까지 가능 + for (int i = 0; i < 10001; i++) { + arr.add(new ArrayList()); + reversedArr.add(new ArrayList()); + } + + // 모든 단어를 접미사 와일드카드 배열, 접두사 와일드카드 배열에 각각 삽입 + 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 + +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 new file mode 100644 index 0000000..4b86c30 --- /dev/null +++ b/16/1.py @@ -0,0 +1,35 @@ +# 테스트 케이스(Test Case) 입력 +for tc in range(int(input())): + # 금광 정보 입력 + n, m = map(int, input().split()) + array = list(map(int, input().split())) + + # 다이나믹 프로그래밍을 위한 2차원 DP 테이블 초기화 + dp = [] + index = 0 + for i in range(n): + dp.append(array[index:index + m]) + index += m + + # 다이나믹 프로그래밍 진행 + for j in range(1, m): + for i in range(n): + # 왼쪽 위에서 오는 경우 + if i == 0: + left_up = 0 + else: + left_up = dp[i - 1][j - 1] + # 왼쪽 아래에서 오는 경우 + if i == n - 1: + left_down = 0 + else: + left_down = dp[i + 1][j - 1] + # 왼쪽에서 오는 경우 + left = dp[i][j - 1] + dp[i][j] = dp[i][j] + max(left_up, left_down, left) + + result = 0 + for i in range(n): + result = max(result, dp[i][m - 1]) + + print(result) 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 + +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 new file mode 100644 index 0000000..3af6fa5 --- /dev/null +++ b/16/2.py @@ -0,0 +1,23 @@ +n = int(input()) +dp = [] # 다이나믹 프로그래밍을 위한 DP 테이블 초기화 + +for _ in range(n): + dp.append(list(map(int, input().split()))) + +# 다이나믹 프로그래밍으로 2번째 줄부터 내려가면서 확인 +for i in range(1, n): + for j in range(i + 1): + # 왼쪽 위에서 내려오는 경우 + if j == 0: + up_left = 0 + else: + up_left = dp[i - 1][j - 1] + # 바로 위에서 내려오는 경우 + if j == i: + up = 0 + else: + up = dp[i - 1][j] + # 최대 합을 저장 + dp[i][j] = dp[i][j] + max(up_left, up) + +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 + +using namespace std; + +int n; // 전체 상담 개수 +vector t; // 각 상담을 완료하는데 걸리는 기간 +vector 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 new file mode 100644 index 0000000..704aab8 --- /dev/null +++ b/16/3.py @@ -0,0 +1,24 @@ +n = int(input()) # 전체 상담 개수 +t = [] # 각 상담을 완료하는데 걸리는 기간 +p = [] # 각 상담을 완료했을 때 받을 수 있는 금액 +dp = [0] * (n + 1) # 다이나믹 프로그래밍을 위한 1차원 DP 테이블 초기화 +max_value = 0 + +for _ in range(n): + x, y = map(int, input().split()) + t.append(x) + p.append(y) + +# 리스트를 뒤에서부터 거꾸로 확인 +for i in range(n - 1, -1, -1): + time = t[i] + i + # 상담이 기간 안에 끝나는 경우 + if time <= n: + # 점화식에 맞게, 현재까지의 최고 이익 계산 + dp[i] = max(p[i] + dp[time], max_value) + max_value = dp[i] + # 상담이 기간을 벗어나는 경우 + else: + dp[i] = max_value + +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 + +using namespace std; + +int n; +vector 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 v = new ArrayList(); + 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 new file mode 100644 index 0000000..bee94df --- /dev/null +++ b/16/4.py @@ -0,0 +1,16 @@ +n = int(input()) +array = list(map(int, input().split())) +# 순서를 뒤집어 '최장 증가 부분 수열' 문제로 변환 +array.reverse() + +# 다이나믹 프로그래밍을 위한 1차원 DP 테이블 초기화 +dp = [1] * n + +# 가장 긴 증가하는 부분 수열(LIS) 알고리즘 수행 +for i in range(1, n): + for j in range(0, i): + if array[j] < array[i]: + dp[i] = max(dp[i], dp[j] + 1) + +# 열외해야 하는 병사의 최소 수를 출력 +print(n - max(dp)) 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 + +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 new file mode 100644 index 0000000..b546154 --- /dev/null +++ b/16/5.py @@ -0,0 +1,27 @@ +n = int(input()) + +ugly = [0] * n # 못생긴 수를 담기 위한 테이블 (1차원 DP 테이블) +ugly[0] = 1 # 첫 번째 못생긴 수는 1 + +# 2배, 3배, 5배를 위한 인덱스 +i2 = i3 = i5 = 0 +# 처음에 곱셈 값을 초기화 +next2, next3, next5 = 2, 3, 5 + +# 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번째 못생긴 수를 출력 +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 + +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 > dp(n + 1, vector(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 new file mode 100644 index 0000000..6ccf896 --- /dev/null +++ b/16/6.py @@ -0,0 +1,32 @@ +# 최소 편집 거리(Edit Distance) 계산을 위한 다이나믹 프로그래밍 +def edit_dist(str1, str2): + n = len(str1) + m = len(str2) + + # 다이나믹 프로그래밍을 위한 2차원 DP 테이블 초기화 + dp = [[0] * (m + 1) for _ in range(n + 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 +#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 +#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 +#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 > > 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 { + + 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 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 +#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정 + +using namespace std; + +// 노드의 개수(N), 간선의 개수(M) +int n, m; +// 시작 노드를 1번 헛간으로 설정 +int start = 1; +// 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기 +vector > graph[20001]; +// 최단 거리 테이블 만들기 +int d[20001]; + +void dijkstra(int start) { + priority_queue > 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 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 { + + 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> graph = new ArrayList>(); + // 최단 거리 테이블 만들기 + public static int[] d = new int[20001]; + + public static void dijkstra(int start) { + PriorityQueue 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()); + } + + // 모든 간선 정보를 입력받기 + 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 result = new ArrayList(); + + 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 + +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 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 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 + +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 + +using namespace std; + +// 노드의 개수와 간선의 개수 +int n, m; +int parent[200001]; // 부모 테이블 초기화 +// 모든 간선을 담을 리스트와, 최종 비용을 담을 변수 +vector > > 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 { + + 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 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 + +using namespace std; + +// 노드의 개수 +int n; +int parent[100001]; // 부모 테이블 초기화 +// 모든 간선을 담을 리스트와, 최종 비용을 담을 변수 +vector > > 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 > x; + vector > y; + vector > 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 { + + 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 { + + 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 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 x = new ArrayList(); + ArrayList y = new ArrayList(); + ArrayList z = new ArrayList(); + + // 모든 노드에 대한 좌표 값 입력받기 + 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 + +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 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 result; // 알고리즘 수행 결과를 담을 리스트 + queue 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 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 result = new ArrayList<>(); // 알고리즘 수행 결과를 담을 리스트 + Queue 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 + +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 + +using namespace std; + +int n = 1000; // 2부터 1,000까지의 모든 수에 대하여 소수 판별 +// 처음엔 모든 수가 소수(True)인 것으로 초기화(0과 1은 제외) +vector 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 + +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 + +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 + +using namespace std; + +void heapSort(vector& arr) { + priority_queue 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 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 + +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 +#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정 + +using namespace std; + +// 노드의 개수(N), 간선의 개수(M) +// 노드의 개수는 최대 500개라고 가정 +int n, m; +// 모든 간선에 대한 정보를 담는 리스트 만들기 +vector > > 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 +#define MAX 100001 + +using namespace std; + +int n, m; +int parent[MAX]; // 부모에 대한 정보 +int d[MAX]; // 각 노드까지의 깊이(depth) +int c[MAX]; // 각 노드의 깊이가 계산되었는지 여부 +vector 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 +#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 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 + +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 + +using namespace std; + +int n, m, k; +vector 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 + +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 bb267f3..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 + +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 + +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 + +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 + +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 75838c6..075404a 100644 --- a/4/3.py +++ b/4/3.py @@ -1,17 +1,15 @@ -# 현재 나이트의 위치 입력 받기 +# 현재 나이트의 위치 입력받기 input_data = input() -row = int(input_data[1]) - 0 +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 for step in steps: + # 이동하고자 하는 위치 확인 next_row = row + step[0] next_column = column + step[1] # 해당 위치로 이동이 가능하다면 카운트 증가 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 + +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 ce657b1..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()))) @@ -31,7 +31,7 @@ def turn_left(): turn_left() nx = x + dx[direction] ny = y + dy[direction] - # 왼쪽 방향에 가보지 않은 칸이 존재하는 경우 이동 + # 회전한 이후 정면에 가보지 않은 칸이 존재하는 경우 이동 if d[nx][ny] == 0 and array[nx][ny] == 0: d[nx][ny] = 1 x = nx @@ -39,14 +39,14 @@ def turn_left(): count += 1 turn_time = 0 continue - # 왼쪽 방향에 가보지 않은 칸이 없는 경우 + # 회전한 이후 정면에 가보지 않은 칸이 없거나 바다인 경우 else: turn_time += 1 # 네 방향 모두 갈 수 없는 경우 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 + +using namespace std; + +stack 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 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 734ebb8..dfdc165 100644 --- a/5/1.py +++ b/5/1.py @@ -10,4 +10,5 @@ stack.append(4) stack.pop() +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 + +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/10.py b/5/10.py index 90766e7..df1b98e 100644 --- a/5/10.py +++ b/5/10.py @@ -1,31 +1,34 @@ # N, M을 공백을 기준으로 구분하여 입력 받기 n, m = map(int, input().split()) + # 2차원 리스트의 맵 정보 입력 받기 -array = [] +graph = [] for i in range(n): - array.append(list(map(int, input()))) + graph.append(list(map(int, input()))) # DFS로 특정한 노드를 방문한 뒤에 연결된 모든 노드들도 방문 def dfs(x, y): # 주어진 범위를 벗어나는 경우에는 즉시 종료 if x <= -1 or x >= n or y <= -1 or y >= m: - return 0 - if array[x][y] == 0: + return False + # 현재 노드를 아직 방문하지 않았다면 + if graph[x][y] == 0: # 해당 노드 방문 처리 - array[x][y] = 1 - # 상, 하, 좌, 우의 위치들도 모두 방문 처리 + graph[x][y] = 1 + # 상, 하, 좌, 우의 위치들도 모두 재귀적으로 호출 dfs(x - 1, y) dfs(x, y - 1) dfs(x + 1, y) dfs(x, y + 1) - return 1 - return 0 + return True + return False -# 모든 노드에 대하여 음료수 채우기 +# 모든 노드(위치)에 대하여 음료수 채우기 result = 0 for i in range(n): for j in range(m): - if dfs(i, j) == 1: + # 현재 위치에서 DFS 수행 + if dfs(i, j) == True: result += 1 print(result) # 정답 출력 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 + +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 > 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 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/11.py b/5/11.py index 2a311c3..cb0d9f6 100644 --- a/5/11.py +++ b/5/11.py @@ -3,9 +3,9 @@ # N, M을 공백을 기준으로 구분하여 입력 받기 n, m = map(int, input().split()) # 2차원 리스트의 맵 정보 입력 받기 -array = [] +graph = [] for i in range(n): - array.append(list(map(int, input()))) + graph.append(list(map(int, input()))) # 이동할 네 가지 방향 정의 (상, 하, 좌, 우) dx = [-1, 1, 0, 0] @@ -13,7 +13,7 @@ # BFS 소스코드 구현 def bfs(x, y): - # 큐(Queue) 구현을 위해 dequue 라이브러리 사용 + # 큐(Queue) 구현을 위해 deque 라이브러리 사용 queue = deque() queue.append((x, y)) # 큐가 빌 때까지 반복하기 @@ -24,17 +24,17 @@ def bfs(x, y): nx = x + dx[i] ny = y + dy[i] # 미로 찾기 공간을 벗어난 경우 무시 - if nx < 0 or ny < 0 or nx >= n or ny >= m: + if nx < 0 or nx >= n or ny < 0 or ny >= m: continue # 벽인 경우 무시 - if array[nx][ny] == 0: + if graph[nx][ny] == 0: continue # 해당 노드를 처음 방문하는 경우에만 최단 거리 기록 - if array[nx][ny] == 1: - array[nx][ny] = array[x][y] + 1 + if graph[nx][ny] == 1: + graph[nx][ny] = graph[x][y] + 1 queue.append((nx, ny)) # 가장 오른쪽 아래까지의 최단 거리 반환 - return array[n - 1][m - 1] + return graph[n - 1][m - 1] # BFS를 수행한 결과 출력 print(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 + +using namespace std; + +queue 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 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 facfc98..c7e4b72 100644 --- a/5/2.py +++ b/5/2.py @@ -12,6 +12,7 @@ queue.append(1) queue.append(4) queue.popleft() -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 + +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 + +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/4.py b/5/4.py index e944e27..1b00a03 100644 --- a/5/4.py +++ b/5/4.py @@ -1,8 +1,9 @@ def recursive_function(i): - # 100번째 출력을 했을 때 종료되도록 종료 조건 명시 + # 100번째 호출을 했을 때 종료되도록 종료 조건 명시 if i == 100: return - print('재귀 함수를 호출합니다.') + print(i, '번째 재귀함수에서', i + 1, '번째 재귀함수를 호출합니다.') recursive_function(i + 1) + print(i, '번째 재귀함수를 종료합니다.') -recursive_function(0) +recursive_function(1) 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 + +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 +#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 + +using namespace std; + +// 행(Row)이 3개인 인접 리스트 표현 +vector > 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> graph = new ArrayList>(); + + public static void main(String[] args) { + // 그래프 초기화 + for (int i = 0; i < 3; i++) { + graph.add(new ArrayList()); + } + + // 노드 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 + +using namespace std; + +bool visited[9]; +vector 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> graph = new ArrayList>(); + + // 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()); + } + + // 노드 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 04f634c..bcd734e 100644 --- a/5/8.py +++ b/5/8.py @@ -1,26 +1,28 @@ # DFS 함수 정의 -def dfs(adj, v, visited): +def dfs(graph, v, visited): # 현재 노드를 방문 처리 - visited.add(v) + visited[v] = True print(v, end=' ') # 현재 노드와 연결된 다른 노드를 재귀적으로 방문 - for i in adj[v]: - if i not in visited: - dfs(adj, i, visited) + for i in graph[v]: + if not visited[i]: + dfs(graph, i, visited) -# 각 노드가 연결된 정보를 dict 자료형으로 표현 (2차원 리스트 대신) -adj = { - 1: [2, 3, 8], - 2: [1, 7], - 3: [1, 4, 5], - 4: [3, 5], - 5: [3, 4], - 6: [7], - 7: [2, 6, 8], - 8: [1, 7] -} -# 각 노드가 방문된 정보를 set 자료형으로 표현 (1차원 리스트 대신) -visited = set() +# 각 노드가 연결된 정보를 리스트 자료형으로 표현(2차원 리스트) +graph = [ + [], + [2, 3, 8], + [1, 7], + [1, 4, 5], + [3, 5], + [3, 4], + [7], + [2, 6, 8], + [1, 7] +] + +# 각 노드가 방문된 정보를 리스트 자료형으로 표현(1차원 리스트) +visited = [False] * 9 # 정의된 DFS 함수 호출 -dfs(adj, 1, visited) +dfs(graph, 1, visited) 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 + +using namespace std; + +bool visited[9]; +vector graph[9]; + +// BFS 함수 정의 +void bfs(int start) { + queue 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> graph = new ArrayList>(); + + // BFS 함수 정의 + public static void bfs(int start) { + Queue 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()); + } + + // 노드 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 e59cb97..c76d400 100644 --- a/5/9.py +++ b/5/9.py @@ -1,35 +1,37 @@ from collections import deque # BFS 함수 정의 -def bfs(adj, start, visited): +def bfs(graph, start, visited): # 큐(Queue) 구현을 위해 deque 라이브러리 사용 queue = deque([start]) # 현재 노드를 방문 처리 - visited.add(start) + visited[start] = True # 큐가 빌 때까지 반복 while queue: - # 큐에서 하나의 원소를 뽑아 출력하기 + # 큐에서 하나의 원소를 뽑아 출력 v = queue.popleft() print(v, end=' ') # 해당 원소와 연결된, 아직 방문하지 않은 원소들을 큐에 삽입 - for i in adj[v]: - if i not in visited: + for i in graph[v]: + if not visited[i]: queue.append(i) - visited.add(i) + visited[i] = True -# 각 노드가 연결된 정보를 dict 자료형으로 표현 (2차원 리스트 대신) -adj = { - 1: [2, 3, 8], - 2: [1, 7], - 3: [1, 4, 5], - 4: [3, 5], - 5: [3, 4], - 6: [7], - 7: [2, 6, 8], - 8: [1, 7] -} -# 각 노드가 방문된 정보를 set 자료형으로 표현 (1차원 리스트 대신) -visited = set() +# 각 노드가 연결된 정보를 리스트 자료형으로 표현(2차원 리스트) +graph = [ + [], + [2, 3, 8], + [1, 7], + [1, 4, 5], + [3, 5], + [3, 4], + [7], + [2, 6, 8], + [1, 7] +] + +# 각 노드가 방문된 정보를 리스트 자료형으로 표현(1차원 리스트) +visited = [False] * 9 # 정의된 BFS 함수 호출 -bfs(adj, 1, visited) +bfs(graph, 1, visited) 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 + +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 + +using namespace std; + +int n; +vector 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 + +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 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 { + + 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 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 + +using namespace std; + +int n, k; +vector 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 + +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 b5383dd..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까지 감소하며 반복하는 문법 - 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 + +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 + +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 +#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 + +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 91a20e3..e5f32c8 100644 --- a/6/8.py +++ b/6/8.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(input().split()) - -# 키(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 + +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 { + + 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 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 + +using namespace std; + +// 순차 탐색 소스코드 구현 +int sequantialSearch(int n, string target, vector 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 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 309f924..0122f30 100644 --- a/7/1.py +++ b/7/1.py @@ -4,7 +4,8 @@ def sequential_search(n, target, array): for i in range(n): # 현재의 원소가 찾고자 하는 원소와 동일한 경우 if array[i] == target: - return i + 1 # 현재의 위치(인덱스) 반환 + 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 + +using namespace std; + +// 이진 탐색 소스코드 구현(재귀 함수) +int binarySearch(vector& 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 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 111e22d..206d704 100644 --- a/7/2.py +++ b/7/2.py @@ -1,23 +1,26 @@ # 이진 탐색 소스코드 구현 (재귀 함수) -def binary_search(start, end, target, array): +def binary_search(array, target, start, end): if start > end: return None mid = (start + end) // 2 + # 찾은 경우 중간점 인덱스 반환 if array[mid] == target: return mid + # 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인 elif array[mid] > target: - return binary_search(start, mid - 1, target, array) + return binary_search(array, target, start, mid - 1) + # 중간점의 값보다 찾고자 하는 값이 큰 경우 오른쪽 확인 else: - return binary_search(mid + 1, end, target, array) + 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())) # 이진 탐색 수행 결과 출력 -result = binary_search(0, n - 1, target, array) +result = binary_search(array, target, 0, n - 1) if result == None: - print(None) + print("원소가 존재하지 않습니다.") else: print(result + 1) 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 + +using namespace std; + +// 이진 탐색 소스코드 구현(반복문) +int binarySearch(vector& 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 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 00634dd..449de3d 100644 --- a/7/3.py +++ b/7/3.py @@ -1,23 +1,26 @@ # 이진 탐색 소스코드 구현 (반복문) -def binary_search(start, end, target, array): +def binary_search(array, target, start, end): while start <= end: mid = (start + end) // 2 + # 찾은 경우 중간점 인덱스 반환 if array[mid] == target: return mid - elif array[mid] < target: - start = mid + 1 - else: + # 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인 + 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())) # 이진 탐색 수행 결과 출력 -result = binary_search(0, n - 1, target, array) +result = binary_search(array, target, 0, n - 1) if result == None: - print(None) + print("원소가 존재하지 않습니다.") else: print(result + 1) diff --git a/7/4.py b/7/4.py index a824b96..48d44fe 100644 --- a/7/4.py +++ b/7/4.py @@ -1,4 +1,6 @@ import sys +# 하나의 문자열 데이터 입력 받기 input_data = sys.stdin.readline().rstrip() +# 입력 받은 문자열 그대로 출력하기 print(input_data) 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 + +using namespace std; + +// 이진 탐색 소스코드 구현(반복문) +int binarySearch(vector& 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 arr; +// 손님이 확인 요청한 부품 번호들 +vector 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/5.py b/7/5.py index 4c9b8c2..cedee53 100644 --- a/7/5.py +++ b/7/5.py @@ -1,14 +1,17 @@ -# 이진 탐색 소스코드 구현 (재귀 함수) -def search(start, end, target, array): - if start > end: - return None - mid = (start + end) // 2 - if array[mid] == target: - return mid - elif array[mid] > target: - return search(start, mid - 1, target, array) - else: - return search(mid + 1, end, target, array) +# 이진 탐색 소스코드 구현 (반복문) +def binary_search(array, target, start, end): + while start <= end: + mid = (start + end) // 2 + # 찾은 경우 중간점 인덱스 반환 + if array[mid] == target: + return mid + # 중간점의 값보다 찾고자 하는 값이 작은 경우 왼쪽 확인 + elif array[mid] > target: + end = mid - 1 + # 중간점의 값보다 찾고자 하는 값이 작은 경우 오른쪽 확인 + else: + start = mid + 1 + return None # N(가게의 부품 개수) 입력 n = int(input()) @@ -23,7 +26,7 @@ def search(start, end, target, array): # 손님이 확인 요청한 부품 번호를 하나씩 확인 for i in x: # 해당 부품이 존재하는지 확인 - result = search(0, n - 1, i, array) + result = binary_search(array, i, 0, n - 1) if result != None: print('yes', end=' ') else: 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 + +using namespace std; + +// N(가게의 부품 개수)와 M(손님이 확인 요청한 부품 개수) +int n, m; +int arr[1000001]; +vector 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 + +using namespace std; + +// N(가게의 부품 개수)와 M(손님이 확인 요청한 부품 개수) +int n, m; +// 가게게 있는 전체 부품 번호를 담을 집합(set) 컨테이너 +set s; +vector 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 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 + +using namespace std; + +// 떡의 개수(N)와 요청한 떡의 길이(M) +int n, m; +// 각 떡의 개별 높이 정보 +vector 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 327832c..4f15658 100644 --- a/7/8.py +++ b/7/8.py @@ -12,16 +12,16 @@ 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 - # 떡볶이 양이 충분한 경우 덜 자르기 + # 떡볶이 양이 충분한 경우 덜 자르기 (왼쪽 부분 탐색) else: - result = mid + result = mid # 최대한 덜 잘랐을 때가 정답이므로, 여기에서 result에 기록 start = 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 + +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 + +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/2.py b/8/2.py index ffb6001..c0e7a2d 100644 --- a/8/2.py +++ b/8/2.py @@ -1,12 +1,12 @@ # 한 번 계산된 결과를 메모이제이션(Memoization)하기 위한 리스트 초기화 d = [0] * 100 -# 피보나치 함수(Fibonacci Function)를 재귀하뭇로 구현 (다이나믹 프로그래밍) +# 피보나치 함수(Fibonacci Function)를 재귀함수로 구현 (탑다운 다이나믹 프로그래밍) def fibo(x): # 종료 조건(1 혹은 2일 때 1을 반환) if x == 1 or x == 2: return 1 - # 이미 계산한 적 있는 결과라면 그대로 반환 + # 이미 계산한 적 있는 문제라면 그대로 반환 if d[x] != 0: return d[x] # 아직 계산하지 않은 문제라면 점화식에 따라서 피보나치 결과 반환 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 + +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 a73ad47..b50b604 100644 --- a/8/3.py +++ b/8/3.py @@ -1,13 +1,12 @@ -# 한 번 계산된 결과를 메모이제이션(Memoization)하기 위한 리스트 초기화 -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 + +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 6048707..cd51f38 100644 --- a/8/4.py +++ b/8/4.py @@ -1,21 +1,13 @@ -# 정수 X를 입력 받기 -x = int(input()) +# 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 +d = [0] * 100 -# 한 번 계산된 결과를 메모이제이션(Memoization)하기 위한 리스트 초기화 -d = [0] * 1000001 +# 첫 번째 피보나치 수와 두 번째 피보나치 수는 1 +d[1] = 1 +d[2] = 1 +n = 99 -# 다이나믹 프로그래밍(Dynamic Programming) 진행 (Bottom-top) -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 + +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 9bba254..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()) -# 한 번 계산된 결과를 메모이제이션(Memoization)하기 위한 리스트 초기화 -d = [0] * 100 +# 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 +d = [0] * 1000001 -# 다이나믹 프로그래밍(Dynamic Programming) 진행 (Bottom-top) -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 + +using namespace std; + +// 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 +int d[100]; +int n; +vector 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 57bdbd5..941e1bc 100644 --- a/8/6.py +++ b/8/6.py @@ -1,13 +1,16 @@ # 정수 N을 입력 받기 n = int(input()) -# 한 번 계산된 결과를 메모이제이션(Memoization)하기 위한 리스트 초기화 -d = [0] * 1000001 +# 모든 식량 정보 입력 받기 +array = list(map(int, input().split())) -# 다이나믹 프로그래밍(Dynamic Programming) 진행 (Bottom-top) -d[1] = 1 -d[2] = 3 -for i in range(3, n + 1): - d[i] = (d[i - 1] + 2 * d[i - 2]) % 796796 +# 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 +d = [0] * 100 + +# 다이나믹 프로그래밍(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]) # 계산된 결과 출력 -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 + +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 6d9428e..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()) -# 한 번 계산된 결과를 메모이제이션(Memoization)하기 위한 리스트 초기화 -d = [10001] * (m + 1) +# 앞서 계산된 결과를 저장하기 위한 DP 테이블 초기화 +d = [0] * 1001 -# 다이나믹 프로그래밍(Dynamic Programming) 진행 (Bottom-top) -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) +# 다이나믹 프로그래밍(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 # 계산된 결과 출력 -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 + +using namespace std; + +int n, m; +vector 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 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 +#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정 + +using namespace std; + +// 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start) +// 노드의 개수는 최대 100,000개라고 가정 +int n, m, start; +// 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열 +vector > 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> graph = new ArrayList>(); + // 방문한 적이 있는지 체크하는 목적의 배열 만들기 + 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()); + } + + // 모든 간선 정보를 입력받기 + 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 06349e9..ad5b9c3 100644 --- a/9/1.py +++ b/9/1.py @@ -1,27 +1,28 @@ import sys input = sys.stdin.readline +INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정 -# 노드의 개수, 간선의 개수를 입력 받습니다. +# 노드의 개수, 간선의 개수를 입력받기 n, m = map(int, input().split()) -# 시작 노드 번호를 입력 받습니다. +# 시작 노드 번호를 입력받기 start = int(input()) -# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만듭니다. -adj = [[] for i in range (n + 1)] -# 방문한 적이 있는지 체크하는 목적의 리스트를 만듭니다. +# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기 +graph = [[] for i in range(n + 1)] +# 방문한 적이 있는지 체크하는 목적의 리스트를 만들기 visited = [False] * (n + 1) -# 최단 거리 테이블을 모두 무한(10억)으로 초기화합니다. -distance = [1e9] * (n + 1) -# 모든 간선 정보를 입력 받습니다. +# 최단 거리 테이블을 모두 무한으로 초기화 +distance = [INF] * (n + 1) +# 모든 간선 정보를 입력받기 for _ in range(m): a, b, c = map(int, input().split()) - # a번 노드에서 b번 노드로 가는 비용이 c라는 의미입니다. - adj[a].append((b, c)) + # a번 노드에서 b번 노드로 가는 비용이 c라는 의미 + graph[a].append((b, c)) -# 방문하지 않은 노드 중에서, 가장 최단 거리가 짧은 노드의 번호를 반환합니다. +# 방문하지 않은 노드 중에서, 가장 최단 거리가 짧은 노드의 번호를 반환 def get_smallest_node(): - min_value = 1e9 - index = 0 + min_value = INF + index = 0 # 가장 최단 거리가 짧은 노드(인덱스) for i in range(1, n + 1): if distance[i] < min_value and not visited[i]: min_value = distance[i] @@ -29,31 +30,31 @@ def get_smallest_node(): return index def dijkstra(start): - # 시작 노드에 대해서 초기화합니다. + # 시작 노드에 대해서 초기화 distance[start] = 0 visited[start] = True - for j in adj[start]: + 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 adj[now]: + # 현재 노드와 연결된 다른 노드를 확인 + 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)이라고 출력합니다. - if distance[i] == 1e9: +# 모든 노드로 가기 위한 최단 거리를 출력 +for i in range(1, n + 1): + # 도달할 수 없는 경우, 무한(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 +#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정 + +using namespace std; + +// 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start) +// 노드의 개수는 최대 100,000개라고 가정 +int n, m, start; +// 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열 +vector > graph[100001]; +// 최단 거리 테이블 만들기 +int d[100001]; + +void dijkstra(int start) { + priority_queue > 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 { + + 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> graph = new ArrayList>(); + // 최단 거리 테이블 만들기 + public static int[] d = new int[100001]; + + public static void dijkstra(int start) { + PriorityQueue 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()); + } + + // 모든 간선 정보를 입력받기 + 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 bf3d1b2..626a496 100644 --- a/9/2.py +++ b/9/2.py @@ -1,47 +1,50 @@ -import queue +import heapq import sys input = sys.stdin.readline +INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정 -# 노드의 개수, 간선의 개수를 입력 받습니다. +# 노드의 개수, 간선의 개수를 입력받기 n, m = map(int, input().split()) -# 시작 노드 번호를 입력 받습니다. +# 시작 노드 번호를 입력받기 start = int(input()) -# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만듭니다. -adj = [[] for i in range (n + 1)] -# 최단 거리 테이블을 모두 무한(10억)으로 초기화합니다. -distance = [1e9] * (n + 1) -# 모든 간선 정보를 입력 받습니다. +# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기 +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라는 의미입니다. - adj[a].append((b, c)) + # a번 노드에서 b번 노드로 가는 비용이 c라는 의미 + graph[a].append((b, c)) def dijkstra(start): - q = queue.PriorityQueue() - # 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입합니다. - q.put((0, start)) - distance[start] = 0 - while not q.empty(): - # 가장 최단 거리가 짧은 노드에 대한 정보를 꺼냅니다. - dist, now = q.get() + 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 adj[now]: + # 현재 노드와 연결된 다른 인접한 노드들을 확인 + for i in graph[now]: cost = dist + i[1] # 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우 - if distance[i[0]] > cost: + if cost < distance[i[0]]: distance[i[0]] = cost - q.put((cost, i[0])) + heapq.heappush(q, (cost, i[0])) -# 다익스트라 알고리즘을 수행합니다. +# 다익스트라 알고리즘을 수행 dijkstra(start) -# 모든 노드로 가기 위한 최단 거리를 출력합니다. -for i in range (1, n + 1): - # 도달할 수 없는 경우, 무한(INFINITY)이라고 출력합니다. - if distance[i] == 1e9: +# 모든 노드로 가기 위한 최단 거리를 출력 +for i in range(1, n + 1): + # 도달할 수 없는 경우, 무한(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 +#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 01492bc..a92ea2b 100644 --- a/9/3.py +++ b/9/3.py @@ -1,38 +1,36 @@ -# 노드의 개수 및 간선의 개수를 입력 받습니다. +INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정 + +# 노드의 개수 및 간선의 개수를 입력받기 n = int(input()) m = int(input()) -# 2차원 리스트를 만들고, 모든 값을 무한으로 초기화합니다. -adj = [[1e9] * (n + 1) for _ in range(n + 1)] +# 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: - adj[a][b] = 0 + graph[a][b] = 0 -# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화합니다. +# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화 for _ in range(m): - # A에서 B로 가는 비용은 C라고 설정합니다. + # A에서 B로 가는 비용은 C라고 설정 a, b, c = map(int, input().split()) - adj[a][b] = c - -# 플로이드 워셜 알고리즘을 정의합니다. -def solve(): - for k in range(1, n + 1): - for a in range(1, n + 1): - for b in range(1, n + 1): - adj[a][b] = min(adj[a][b], adj[a][k] + adj[k][b]) + graph[a][b] = c -# 플로이드 워셜 알고리즘을 수행합니다. -solve() +# 점화식에 따라 플로이드 워셜 알고리즘을 수행 +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)이라고 출력합니다. - if adj[a][b] == 1e9: - print("INF", end=" ") - # 도달할 수 있는 경우 거리를 출력합니다. + # 도달할 수 없는 경우, 무한(INFINITY)이라고 출력 + if graph[a][b] == 1e9: + print("INFINITY", end=" ") + # 도달할 수 있는 경우 거리를 출력 else: - print(adj[a][b], end=" ") + 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 +#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 1b5c379..bffb30a 100644 --- a/9/4.py +++ b/9/4.py @@ -1,37 +1,38 @@ -# 노드의 개수 및 간선의 개수를 입력 받습니다. +INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정 + +# 노드의 개수 및 간선의 개수를 입력받기 n, m = map(int, input().split()) -# 2차원 리스트를 만들고, 모든 값을 무한으로 초기화합니다. -adj = [[1e9] * (n + 1) for _ in range(n + 1)] +# 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: - adj[a][b] = 0 + graph[a][b] = 0 -# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화합니다. +# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화 for _ in range(m): - # A와 B가 서로에게 가는 비용은 1이라고 설정합니다. + # A와 B가 서로에게 가는 비용은 1이라고 설정 a, b = map(int, input().split()) - adj[a][b] = 1 - adj[b][a] = 1 + graph[a][b] = 1 + graph[b][a] = 1 -# 거쳐 갈 노드 x와 최종 목적지 노드 k를 입력 받습니다. +# 거쳐 갈 노드 X와 최종 목적지 노드 K를 입력받기 x, k = map(int, input().split()) -# 플로이드 워셜 알고리즘을 정의합니다. -def solve(): - for k in range(1, n + 1): - for a in range(1, n + 1): - for b in range(1, n + 1): - adj[a][b] = min(adj[a][b], adj[a][k] + adj[k][b]) +# 점화식에 따라 플로이드 워셜 알고리즘을 수행 +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]) -# 플로이드 워셜 알고리즘을 수행합니다. -solve() +# 수행된 결과를 출력 +distance = graph[1][k] + graph[k][x] -# 수행된 결과를 출력합니다. -distance = adj[1][k] + adj[k][x] +# 도달할 수 없는 경우, -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 +#define INF 1e9 // 무한을 의미하는 값으로 10억을 설정 + +using namespace std; + +// 노드의 개수(N), 간선의 개수(M), 시작 노드 번호(Start) +int n, m, start; +// 각 노드에 연결되어 있는 노드에 대한 정보를 담는 배열 +vector > graph[30001]; +// 최단 거리 테이블 만들기 +int d[30001]; + +void dijkstra(int start) { + priority_queue > 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 { + + 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> graph = new ArrayList>(); + // 최단 거리 테이블 만들기 + public static int[] d = new int[30001]; + + public static void dijkstra(int start) { + PriorityQueue 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()); + } + + // 모든 간선 정보를 입력받기 + 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 8478604..9d780be 100644 --- a/9/5.py +++ b/9/5.py @@ -1,49 +1,51 @@ -import queue +import heapq import sys input = sys.stdin.readline +INF = int(1e9) # 무한을 의미하는 값으로 10억을 설정 -# 노드의 개수, 간선의 개수, 시작 노드를 입력 받습니다. +# 노드의 개수, 간선의 개수, 시작 노드를 입력받기 n, m, start = map(int, input().split()) -# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만듭니다. -adj = [[] for i in range (n + 1)] -# 최단 거리 테이블을 모두 무한(10억)으로 초기화합니다. -distance = [1e9] * (n + 1) +# 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트를 만들기 +graph = [[] for i in range(n + 1)] +# 최단 거리 테이블을 모두 무한으로 초기화 +distance = [INF] * (n + 1) -# 모든 간선 정보를 입력 받습니다. +# 모든 간선 정보를 입력받기 for _ in range(m): x, y, z = map(int, input().split()) - # a번 노드에서 b번 노드로 가는 비용이 c라는 의미입니다. - adj[x].append((y, z)) + # X번 노드에서 Y번 노드로 가는 비용이 Z라는 의미 + graph[x].append((y, z)) def dijkstra(start): - q = queue.PriorityQueue() - # 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입합니다. - q.put((0, start)) + q = [] + # 시작 노드로 가기 위한 최단 경로는 0으로 설정하여, 큐에 삽입 + heapq.heappush(q, (0, start)) distance[start] = 0 - while not q.empty(): - # 가장 최단 거리가 짧은 노드에 대한 정보를 꺼냅니다. - dist, now = q.get() + while q: # 큐가 비어있지 않다면 + # 가장 최단 거리가 짧은 노드에 대한 정보를 꺼내기 + dist, now = heapq.heappop(q) if distance[now] < dist: continue - # 현재 노드와 연결된 다른 인접한 노드들을 확인합니다. - for i in adj[now]: + # 현재 노드와 연결된 다른 인접한 노드들을 확인 + for i in graph[now]: cost = dist + i[1] # 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧은 경우 - if distance[i[0]] > cost: + if cost < distance[i[0]]: distance[i[0]] = cost - q.put((cost, i[0])) + 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을 출력 print(count - 1, max_distance) diff --git a/README.md b/README.md index 951ea73..8adf9d3 100644 --- a/README.md +++ b/README.md @@ -1,179 +1,350 @@ -### 알고리즘 코딩 테스트 합격을 위한 파이썬 비법 노트 +### 이것이 취업을 위한 코딩 테스트다 with Python +> 취업과 이직을 결정하는 알고리즘 인터뷰 완벽 가이드 (2020년 08월 05일 정식 출시) + +* 이 저장소는 이것이 취업을 위한 코딩 테스트다 with Python (나동빈 저, 한빛미디어) 전체 소스코드를 포함합니다. +* 본 책은 Python 3.7 문법을 활용하였으나, 추가적으로 Java, C++11 소스코드를 제공합니다. +* 책 내용 및 소스코드와 관련한 궁금한 점은 [Issues](https://github.com/ndb796/python-for-coding-test/issues) 탭을 이용하여 남겨주세요. +* 책의 오류 사항을 발견하시면 dongbinna@postech.ac.kr로 보내주시면 감사하겠습니다. + * 이 경우, 원하신다면 [정오표](/notice.md)에 독자님의 이름(혹은 아이디)을 함께 기재해드립니다. +* 이 책을 이용해 강의를 진행하시는 교수/선생님/강사/동아리장 님들을 위해 강의용 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) 탭을 이용하여 남겨주세요. +
+ +### 대기업 코딩 테스트 문제 적중 관련 + +* 최근 2021 K사 공채 코딩 테스트 1차 합격 커트라인은 3문제 ~ 3.5문제(부분점수 포함)로 예상됩니다. +* 저자 또한 코딩 테스트에 참여해 보았고, 파이썬만 이용하여 알고리즘 코딩 테스트에 합격할 수 있었습니다. +* 특히 아래 두 문제는 본 책의 파이썬 코드를 참고하여 쉽게 해결할 수 있었습니다. + +* 3번 문제 (이진 탐색): 책의 15장 [정렬된 배열에서 특정 수의 개수 구하기](/15/1.py) 알고리즘을 활용하면 쉽게 풀 수 있는 문제였습니다. + * 파이썬의 bisect_left 함수를 활용합니다. +* 4번 (플로이드 워셜): 책의 9장 [미래 도시](/9/4.py) 문제와 접근 방법 및 아이디어가 사실상 동일한 문제입니다. + * 특정한 중간 지점을 거쳐 갈 때의 최단 경로 알고리즘으로 볼 수 있습니다. + * 저자 개인적으로도 이 문제는 보자마자 풀어서 7분 이내로 풀 수 있었습니다.
-### 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) + +#### 2장 16~20년 코딩 테스트 기출문제 유형 분석 + +* 최신 출제 경향과 준비 방향 +* 연도별 코딩 테스트 유형 분석 -### Part 2 알고리즘 이론과 실전 +#### 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장 그리디 -* [양팔 저울로 무게 재기](https://www.acmicpc.net/problem/2437) (BOJ 문제집) -* \* 혹은 +로 연산하기 (Facebook 인터뷰 기출) -* 볼링공 고르기 (S 기관 입학 테스트) -* [무지의 먹방 라이브](https://www.acmicpc.net/problem/2437) (카카오) -* [문자열 뒤집기](https://www.acmicpc.net/problem/1439) (BOJ 문제집) - +* 모험가 길드 (핵심 유형): ([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/18312) (국내 S 교육 기관 선발 평가) -* [스타트와 링크](https://www.acmicpc.net/problem/14889) (삼성) -* [다트 게임](https://programmers.co.kr/learn/courses/30/lessons/17682) (카카오) -* [뱀](https://www.acmicpc.net/problem/3190) (삼성) -* [치킨 배달](https://www.acmicpc.net/problem/15686) (삼성) -* 문자열 재정렬 (Facebook 인터뷰 기출) +* [럭키 스트레이트](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/14502) (삼성) -* [연산자 끼워넣기](https://www.acmicpc.net/problem/14888) (삼성) -* [괄호 변환](https://programmers.co.kr/learn/courses/30/lessons/60058) (카카오) -* [인구 이동](https://www.acmicpc.net/problem/16234) (삼성) -* [구슬 탈출 2](https://www.acmicpc.net/problem/13460) (삼성) -* [나 잡아 봐라](https://engineering.linecorp.com/ko/blog/2019-firsthalf-line-internship-recruit-coding-test/) (Line) +* [특정 거리의 도시 찾기](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) (BOJ 문제집) -* [실패율](https://programmers.co.kr/learn/courses/30/lessons/42889) (카카오) -* [안테나](https://www.acmicpc.net/problem/18310) (국내 S 교육 기관 선발 평가) -* [파일명 정렬](https://programmers.co.kr/learn/courses/30/lessons/17686) (카카오) -* [카드 정렬하기](https://www.acmicpc.net/problem/1715) (BOJ 문제집) +* [국영수](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장 이진 탐색 -* [고정점 찾기](https://www.geeksforgeeks.org/find-a-fixed-point-in-a-given-array/) (Amazon 인터뷰 기출) -* [특정 수만큼 차이나는 한 쌍 찾기](https://www.geeksforgeeks.org/find-a-pair-with-the-given-difference/) (Amazon 인터뷰 기출) -* [정렬된 배열에서 특정 수의 개수 구하기](https://www.geeksforgeeks.org/count-number-of-occurrences-or-frequency-in-a-sorted-array/) (Zoho 인터뷰 기출) -* [공유기 설치](https://www.acmicpc.net/problem/2110) (BOJ 문제집) +* 정렬된 배열에서 특정 수의 개수 구하기 (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장 다이나믹 프로그래밍 -* [퇴사](https://www.acmicpc.net/problem/14501) (카카오) -* [보행자 천국](https://programmers.co.kr/learn/courses/30/lessons/1832) (카카오) -* [편집 거리](https://www.geeksforgeeks.org/edit-distance-dp-5/) (Goldman Sachs 인터뷰 기출) -* [못생긴 수들](https://www.geeksforgeeks.org/ugly-numbers/) (Google 인터뷰 기출) -* [금광 문제](https://www.geeksforgeeks.org/gold-mine-problem/) (Flipkart 인터뷰 기출) -* [정수 삼각형](https://www.acmicpc.net/problem/1932) (IOI) +* 금광 (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/10159) (BOJ 문제집) -* [키 순서](https://www.acmicpc.net/problem/2458) (한국 정보 올림피아드) -* [녹색 옷 입은 애가 젤다지?](https://www.acmicpc.net/problem/4485) (ICPC) -* [숨바꼭질](https://www.acmicpc.net/problem/6118) (COCI) - +* [플로이드](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장 기타 그래프 이론 -* [여행 가자](https://www.acmicpc.net/problem/1976) (BOJ 문제집) -* [문자열 압축](https://www.acmicpc.net/problem/10775) (CCC Senior Division) -* [전력난](https://www.acmicpc.net/problem/6497) (University of Ulm Local Contest) -* [행성 터널](https://www.acmicpc.net/problem/2887) (COCI) -* [최종 순위](https://www.acmicpc.net/problem/3665) (NWERC 2010) +* 여행 계획 (핵심 유형): ([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 코딩 테스트를 위한 파이썬 문법 + +* 자료형 + * 수 자료형 + * 정수형 + * 실수형 + * 수 자료형의 연산 + * 리스트 자료형 + * 리스트 만들기 + * 리스트 인덱싱 + * 리스트 슬라이싱 + * 리스트 컴프리헨션 + * 리스트 관련 메서드 + * 문자열 자료형 + * 문자열 초기화 + * 문자열 연산 + * 튜플 자료형 + * 튜플 초기화 + * 사전 자료형 + * 사전 자료형 초기화 + * 사전에서 키로 검색 + * 사전 자료형 관련 메서드 + * 집합 자료형 + * 집합 초기화 + * 집합 연산 + * 집합 관련 메서드 +* 조건문 + * 조건문 예시 1 + * 조건문 예시 2 + * 조건문 예시 3 + * pass 키워드 사용 예시 + * 조건문 한 줄에 쓰기 + * 조건부 표현식 +* 반복문 + * while 문법 + * while 문법 예시 1 + * while 문법 예시 2 + * for 문법 + * for 문법 예시 1 + * for 문법 예시 2 + * for 문법 예시 3 + * for 문법 예시 4 +* 함수 + * 더하기 함수 + * global 키워드 사용 예시 +* 입출력 + * 코딩 테스트에서 입력을 위한 전형적인 코드 + * 공백을 기준으로 적은 수의 데이터 입력 + * readline()으로 빠르게 입력 받기 + * f-string 사용 예시 +* 주요 라이브러리의 문법과 유의점 + * 내장 함수 + * itertools + * heapq + * bisect + * collections + * math +* 자신만의 알고리즘 노트 만들기 + +#### 부록 B 기타 알고리즘 + +* 이론 + * 소수 판별: ([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) +* 실전 + * [소수 구하기](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) 이진 탐색 소스코드 주석 오류 + +* 주석에서 "# 중간점의 값보다 찾고자 하는 값이 경우 오른쪽 확인"이 올바른 내용입니다. + +#### (197p) '부품 찾기' 문제의 입력 조건 및 소스코드 오류 + +* 문제의 조건에서 N개의 정수와 M개의 정수 모두 크기는 1보다 크고 1,000,000이하입니다. +* '계수 정렬'을 이용한 답안에서 array 리스트 변수의 크기는 1,000,001입니다. + +#### (221p) 그림 내 오탈자 + +* 그림 ⓑ에서 그림의 오른쪽 부분은 '털 수 있음'인데 잘못 기재되어 있습니다. + +#### (226p) 출력 조건 오탈자 + +* 출력 조건으로 "첫째 줄에 M 원을 만들기 위한 최소한의 화폐 개수를 출력한다."가 올바른 내용입니다. + +#### (263p) 주석 오탈자 + +* 주석에서 "# x번 노드에서 y번 노드로 가는 비용이 z라는 의미"가 올바른 내용입니다. + +#### (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) 두 번째 예시 본문 단어 표기 오류 + +* 두 번째 예시는 최대 힙을 구현하여 내림차순 힙 정렬을 구현하는 예시입니다. + +#### (483p) 세 번째 쿼리 설명 오류 + +* 세 번째 쿼리는 세 번째 수부터 네 번째 수까지의 구간 합을 물어보는 [3, 4]입니다. + +### 초판 2쇄 + +#### (255p) 수식 오탈자 + +* 수식에서 "D12 + D23 = 11과 비교해서 11로 갱신된다."가 올바른 내용입니다. + +#### (514p) 풀이 설명 오류 + +* \[Step 2\]의 내용은 다음과 같이 변경되어야 올바른 내용입니다. +> 전체 남은 시간은 3초이고, 이번 단계에서는 2번 음식을 빼야 한다. 전체 음식이 2개 남아 있으므로 이번 단계에서 뺄 시간은 2(남은 음식의 개수) X 2(2번 음식을 다 먹는 시간) = 4초가 된다. 하지만 현재 전체 남은 시간이 3초인데, 이는 4보다 작으므로 빼지 않도록 한다. + +#### (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 이상이 아닌 0 이상입니다. + +#### (398p) 문제 내용 오탈자 + +* 문제 설명에서 두 행성 A와 B를 터널로 연결할 때 드는 비용으로는 min(|xA-xB|, |yA-yB|, |zA-zB|)가 올바른 내용입니다.