알고리즘 8

[BOJ/12886/Golang] 백준 12886 - 돌 그룹

문제로 이동하기 https://www.acmicpc.net/problem/12886 여담 Gold 5 문제입니다. BFS에는 나름 자신감이 붙게 만들어준 문제입니다. 이제는 Gold도 두렵지 않다..! 뭐 이런거죠 ㅋㅋㅋ.. 사실 흔한 BFS 문제들과 비슷한 패턴으로 풀리는 문제라서.. 크게 어렵진 않습니다. 접근 방식 우선 상황에 대한 정리가 필요합니다. 현재 주어진 정점은 무엇이고, 가고자 하는 정점은 무엇인지 알아야 합니다. 그리고 현재 주어진 정점에서 이동할 수 있는 방법의 수, 다시 말해 간선의 종류는 어떻게 되는지 정리해볼 필요가 있습니다. 현재 주어진 정점 현재 주어진 정점은 당연하게도 (A, B, C) 입니다. 가고자 하는 정점 모든 그룹에 있는 돌의 개수를 같게 만드는 상황이 목표입니다...

PS/BOJ 2021.06.08

[BOJ/13549/Golang] 백준 13549 - 숨바꼭질 3 - BFS로 풀이

문제로 이동하기 https://www.acmicpc.net/problem/13549 접근 방식 앞서 소개 드렸던 이모티콘 문제와 마찬가지로, 이 문제도 BFS와 DP 모두 사용이 가능합니다. 저는 BFS로 해결했는데, 결과를 보니 DP에 비해 시간과 메모리 모든 면에서 처참했습니다 ㅜㅜ 추후 DP로 해결하는 방법도 포스팅하겠습니다. 이 문제에서 중요한 키워드는 "순간이동을 하는 경우에는 '0초' 후에 이동" 입니다. 즉, 가중치가 0인 간선이 존재한다는 것인데요, 지금까지 BFS로 풀 수 있는 중요한 키워드가 되는 말이 가중치가 모두 1이다. 라는 점이었다는 것을 생각해보면, 이 문제를 BFS로 접근할 수 없는 것이 아닌가 싶을 수 있는데요. 두 가지 방법을 생각해볼 수 있습니다. 큐 두 ..

PS/BOJ 2021.06.04

[BOJ/1629/Golang] 백준 1629 - 곱셈

접근 방식 처음엔 그냥 막 곱하면 되는 줄 알았습니다. 생각해보니 21억번을 제곱하려면, 그냥 곱해서는 안 되고, memoization이라도 해야하나 싶었습니다. 하지만 memoization도 적당히 공간을 잡아야 쓸 수 있지, 21억 개를 모두 배열에 넣는 건 무리수라고 봤습니다. 문제 분류를 보니, 분할정복을 이용한 거듭제곱 이라고 적혀있었습니다. 방법은 굉장히 간단합니다. 재귀함수를 구성해서 연속해서 반씩 쪼개어 분할정복을 하는 겁니다. 이 때 곱셈의 수가 홀수면, 짝수 하나와 홀수 하나로 나눕니다. 이렇게 되면 짝수로 나눠진 거듭제곱은 한 번 구한 값을 두 번 곱하면 되므로, 연산이 줄게 됩니다. 설명 보다는 코드를 보고 이해하시는게 더 빠를 것 같습니다. 코드 package main import..

PS/BOJ 2021.05.31

[BOJ/12969/Golang] 백준 12969 - ABC

접근 방식 앞선 포스트에서 소개한 14238번 문제인 '출근 기록' 문제와 유사한 문제입니다. 문제의 조건 하루에 한 명씩 출근한다. 문자열의 길이 = 출근 기록의 길이(N) A는 본인 스스로 짝을 이룰 수 없다. B는 A와 짝을 이룰 수 있다. C는 A, B 모두와 짝을 이룰 수 있다. 반드시 필요한 조건만 정리해보면, 문자열의 길이인 i가 필요합니다. 또한 A가 몇 개 있는지, B가 몇 개 있는지, C가 몇 개 있는지 알아야 합니다. 마지막으로 쌍의 개수를 계속 체크해주어야 하므로, 쌍의 개수도 나타나야 합니다. 그런데 여기에서 변수를 하나 줄일 수 있습니다. 바로 C인데요. C의 개수는 전체 문자열의 길이에서 A의 개수와 B의 개수를 빼준 크기입니다. 따라서, 실질적으로 사용하게 되는..

PS/BOJ 2021.05.24

[BOJ/14238/Golang] 백준 14238 - 출근 기록

접근 방식 이 문제는 앞으로 정리할 문제인 12969번의 ABC 문제와 유사한 문제입니다. 아무리 생각해도 점화식이 떠오르지 않아 강의를 듣고 이해한 내용을 정리해봅니다. 문제의 조건 하루에 한 명씩 출근한다. 문자열의 길이 = 출근 기록의 길이(N) A는 매일 출근이 가능하다. B는 출근한 다음 날에는 쉬어야 한다. C는 출근한 다음 날과 다다음 날은 쉬어야 한다. 반드시 필요한 조건만 정리해보면, A가 출근한 횟수, B가 출근한 횟수, C가 출근한 횟수가 필요합니다. 또한 B와 C처럼 전날과 전전날의 출근자를 알아야만 상황이 정의되는 사람을 표현하기 위해 전날 출근자(P1)와 전전날 출근자(P2)의 정보도 필요합니다. 참고로 12969번 ABC 문제는 전체 문자열의 길이를 알고 A와 B의 개수가 정해..

PS/BOJ 2021.05.23

[BOJ/5582/Golang] 백준 5582 - 공통 부분 문자열

접근 방식 이 문제는 직전 문제인 LCS (9251) 문제와 동일합니다. 다만 한 가지 더 출력해야 하는데요. 바로 찾은 LCS의 길이 뿐만 아니라, LCS 부분 수열 자체도 출력해야 합니다. 이 문제를 보고 처음 든 생각은, 아 뭔가 부모를 찾고 찾아서 거꾸로 이동하면서 출력하면 되겠구나.. 였습니다. 하지만 부모를 찾아갈 때 어떤 조건을 기준으로 이동할 것인지 생각하는 부분이 어려웠습니다. 중요한 점은 이전에 LCS의 길이가 증가할 때를 살펴보면, [i] == B[j]인 경우였습니다. 이 경우에 D[i][j] = D[i-1][j-1] + 1을 이용할 수 있었죠. 부분 수열 자체를 찾기 위한 꼬리에 꼬리를 무는 이동 조건도 이와 유사합니다. 이 전에 D[i-1][j] 또는 D[i][j-1]은 일치하지 ..

PS/BOJ 2021.05.21

[BOJ/9251/Golang] 백준 9251 - LCS

접근 방식 이 문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것의 길이를 찾는 문제입니다.. 문제에서 예로 든 것은 ACAYKP와 CAPCAK의 LSC인데요. 이 둘의 LCS는 ACAK가 됩니다. 여담으로, LCS는 Longest Common Subsequence의 약자입니다. Substring과의 다른 점은, Substring은 연속으로 붙어 있어야 한다는 제약이 있는 반면에, Subsequence는 그러한 제약이 없다는 점입니다. 백준 강의를 들어보니, 두 문자열의 LCS는 다음과 같다고 설명하고 있습니다. 두 문자열의 LCS는 다음과 같이 같은 문자가 일치하게 공백을 삽입하는 것과 같다고 볼 수 있다. A = "ACAYKP" B = "CAPCA_K_" 그러나 제가 참고한..

PS/BOJ 2021.05.17

[BOJ/11058/Golang] 백준 11058 - 크리보드

백준 11058 - 크리보드 [Gold/5] - Golang 접근 방식 DP로 접근할 수 있다. 힌트에도 주어져 있지만, 큰 문제를 작은 문제로 잘게 나누어 풀 수 있기 때문이다. 순서 TBD 코드 package main import ( "bufio" "fmt" "os" "strconv" ) var ( w = bufio.NewWriter(os.Stdout) sc = bufio.NewScanner(os.Stdin) ) var ( D [101]int N int ) func init() { sc.Split(bufio.ScanWords) } func main() { defer w.Flush() N = scanInt() D[1], D[2], D[3] = 1, 2, 3 for i := 4; i

PS/BOJ 2021.05.16