본문 바로가기

알고리즘22

[BOJ 5247] 불 https://www.acmicpc.net/problem/5427 5427번: 불 문제 상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다. 매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에는 불이 붙지 않는다. 상근이는 동서남북 인접한 칸으로 이동할 수 있으며, 1초가 걸린다. 상근이는 벽을 통과할 수 없고, 불이 옮겨진 칸 또는 이제 불이 붙으려는 칸으로 이동할 수 없다. 상근이가 있는 칸에 불이 옮겨옴과 동시에 다른 칸으로 이동할 수 있다. 빌딩 www.acmicpc.net 위 문제는 여러 테스트 케이스가 주어지고, 맵의 크기도 1000이 되기 때문에 상근이가 이동할 때마다 불을 옮기면 시간초과가 날 수 있다. 그.. 2020. 4. 8.
[BOJ 2352] 반도체 설계 https://www.acmicpc.net/problem/2352 2352번: 반도체 설계 첫째 줄에 정수 n(1 ≤ n ≤ 40,000)이 주어진다. 다음 줄에는 차례로 1번 포트와 연결되어야 하는 포트 번호, 2번 포트와 연결되어야 하는 포트 번호, …, n번 포트와 연결되어야 하는 포트 번호가 주어진다. 이 수들은 1 이상 n 이하이며 서로 같은 수는 없다고 가정하자. www.acmicpc.net 위 그림에서 왼쪽의 포트가 연결된 오른쪽 포트의 번호를 A[i]라고 하고, 선택된 오른쪽 포트를 모아놓은 리스트를 L이라고 두면, 가장 많은 포트를 고르기 위해서는 리스트 L의 원소들이 정렬되어 있는 상태에서 크기가 가장 커야 한다. 예를 들어, 왼쪽 포트 1부터 차례대로 선택할 때, 오른쪽의 3번 포트가.. 2020. 4. 8.
[BOJ 14002] 가장 긴 증가하는 부분 수열 4 https://www.acmicpc.net/problem/14002 14002번: 가장 긴 증가하는 부분 수열 4 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다. www.acmicpc.net [BOJ 11053] 가장 긴 증가하는 부분 수열 과 똑같이 길이를 구한 뒤에 dp의 맨 끝부터 탐색을 하면서 가능한 최대 길이랑 같은지 다른지를 확인하면 된다. 같은 값이 나올 때마다 최대 길이를 1씩 줄여서 dp[i]에서 가능한 최대 길이를 구하면 된다. #include #include #de.. 2020. 4. 7.
[BOJ 12738] 가장 긴 증가하는 부분 수열 3 https://www.acmicpc.net/problem/12738 12738번: 가장 긴 증가하는 부분 수열 3 첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (-1,000,000,000 ≤ Ai ≤ 1,000,000,000) www.acmicpc.net [BOJ 12015] 가장 긴 증가하는 부분 수열 2 과 풀이는 똑같다. 같은 코드로 통과가 된다. #include #include #include using namespace std; int n; int main() { scanf("%d", &n); vector dp; for (int i = 1; i dp.back()) dp.push_back(t); else { v.. 2020. 4. 7.
가장 긴 증가하는 부분 수열, LIS(Longest Increasing Subsequence) LIS는 어떠한 수열에서 증가하는 부분 수열중 길이가 가장 긴 수열를 뜻합니다. LIS를 찾는 알고리즘은 다이나믹 프로그래밍을 이용한 O(N^2) 알고리즘과 이보다는 좀 더 복잡한 O(N log N) 알고리즘이 있습니다. 부분 수열이란 어떠한 수열에서 일부 숫자를 지워서 만들 수 있는 새로운 수열을 의미합니다. O(N^2) O(N^2) 알고리즘은 비교적 간단하게 구현할 수 있습니다. dp[i] = i 번째 원소를 마지막으로 하는 LIS의 길이 dp[i]를 구하는 법은 1 ~ (i - 1)까지의 원소들 중 i번째 원소보다 값이 작은 것들 중 dp의 값이 가장 큰 것에 1을 더하면 된다. 즉, j = 1 ~ (i - 1)을 순회할 때, a[i]보다 a[j]가 작다면, dp[i] = max(dp[i], dp[.. 2020. 4. 7.
[BOJ 11053] 가장 긴 증가하는 부분 수열 https://www.acmicpc.net/problem/11053 11053번: 가장 긴 증가하는 부분 수열 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다. www.acmicpc.net 가장 긴 증가하는 부분 수열의 길이를 구하는 문제이다. 굳이 연속적인 배열이 아니여도 상관없다. 주어진 수열을 순회하면서, 각 순회마다 현재위치에서 첫번째 위치까지 돌면서 각 위치의 값보다 현재 위치의 값이 크면 현재 위치까지의 가장 긴 증가수열은 각 위치의 길이 + 1이다. 이를 통해서 구하면 된다.. 2020. 4. 7.
[BOJ 2606] 바이러스 https://www.acmicpc.net/problem/2606 2606번: 바이러스 첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어진다. 이어서 그 수만큼 한 줄에 한 쌍씩 네트워크 상에서 직접 연결되어 있는 컴퓨터의 번호 쌍이 주어진다. www.acmicpc.net 위 문제는 간단하게 BFS로 풀 수 있다. 1번 컴퓨터에서 갈 수 있는 모든 컴퓨터를 구하면, 몇 개의 컴퓨터가 바이러스에 걸리는지 알 수 있다. 이를 위해서 큐에 1번을 넣음 큐에서 값을 하나 꺼냄 꺼낸 값과 연결된 모든 값 중 방문하지 않은 곳을 큐에 넣음 큐에 넣을 때마다 바이러스가 걸린 컴.. 2020. 4. 7.
Lower Bound & Upper Bound Lower Bound & Upper Bound은 이분 탐색에서 파생된 알고리즘으로 Lower Bound는 "찾는 값 T 이상이 처음 나오는 위치를 찾는" 알고리즘이고, Upper Bound는 "찾는 값 T 초과한 값이 처음 나오는 위치를 찾는" 알고리즘이고, Lower Bound 알고리즘 자체는 이분 탐색과 매우 유사하다. 중간 값이 작으면 시작 위치를 중간 다음 위치로, 크거나 같으면 끝 위치를 중간 위치로 이동시킨다. 이분 탐색과는 다르게 끝 위치를 중간 이전 위치가 아닌 중간 위치로 움직인다. 간단하게 생각해보면 값이 작다는 건 중간 위치까지는 원하는 값 이상이 절대 없기에 다음 위치로 이동시키지만, 크거나 같다면 중간 위치의 값이 찾는 값 이상인 처음 위치일 수도 있기에 중간 위치로 설정한다. #.. 2020. 4. 3.
[정렬] 선택 정렬 (Selection Sort) 원소를 넣을 위치를 정해놓고 어떤 원소를 넣을지 찾아서 정렬한다. 오름차순의 경우, 가장 작은 값을 찾아서 왼쪽부터 정렬을 하거나, 가장 큰 값을 찾아 오른쪽부터 정렬을 하는 방식이다. 1. i = ( 1 ~ (n - 1) )인덱스까지 탐색 2. j = ( (i + 1) ~ n ) 인덱스까지 탐색 3. j의 값 중에 가장 작은 값을 찾아 i번째의 값과 위치를 바꾼다. 4. 위 과정 반복 코드 구현 #include void PrintArray(int* arr, int size) { for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } void Selection(int* arr, int size) { int min, tmp; fo.. 2020. 1. 20.