Coding Test/Baekjoon 17

[C++] 백준 11049: 행렬 곱셈 순서 (동적계획법)

https://www.acmicpc.net/problem/11049소요 시간: 58분해결: O 풀이 설계하는데 시간이 조금 걸렸습니다.풀고 보니 직관적인 문제인데 ps 조금 쉬었더니 바로 둔해지네요...문제 분할일련의 행렬들의 곱이 주어졌을 때, 어디서부터 어떤 순서로 곱해야 가장 적게 계산할까요?... 잘 모르겠습니다. 반대로 그 행렬들을 모두 곱한 결과가 있을 때, 마지막에 어느 부분에서 곱셈이 발생했을까요?마지막 결과 또한 부분 행렬 A와 B를 곱한 결과일테니, 그 경계가 되는 행렬을 찾으면 문제를 분할할 수 있습니다. i번째 행렬이 그 경계라면 아래처럼 식을 정리할 수 있습니다.캐싱start~end까지 행렬을 곱했을 때 연산횟수 중 최솟값을 저장합니다.코드const int INF = numeric..

[C++] 백준 2143: 두 배열의 합

https://www.acmicpc.net/problem/2143 시간: 1시간 11분해결: X문제두 정수 배열 A, B의 연속 부분합을 더해서 T와 같은 경우의 수를 구해야 합니다.저는 문제를 두 개로 나눴습니다. 모든 부분합 구하기A의 모든 부분합 SA의 크기는 1+2+3+ ... +n이므로 아래와 같습니다.B의 모든 부분합 SB도 똑같습니다. 부분합 더하기SA와 SB의 원소를 직접 더 해봅니다.다만 모든 경우의 수를 전부 구하면 대충 O(n^2*m^2)에 가까워지니 방법이 필요합니다. 제가 시도한 방법은1. 모든 SA의 원소 a에 대해 합이 T가 되는 SB의 원소 b를 이분 탐색2. lower_bound()로 a+b=T인 가장 작은 인덱스의 원소를 구하고 하나씩 세기3. (채택) equal_ran..

[C++] 백준 9465: 스티커

안녕하세요 오늘 풀어볼 문제는 스티커 입니다.https://www.acmicpc.net/problem/9465 스티커는 dp 문제인데 기본 DFS에 결합한 형태와는 조금 다른 문제에요.단순히 2차원 배열을 탐색하며 재귀 호출하는 방식이 아니고 점화식을 정의해줘야 합니다.점화식을 정의하기 위해 문제를 개념적으로 뜯어보겠습니다.우선 스티커의 1~n번째 열을 순차로 탐색하는 걸 전제로 할게요.그리고 지금 k번째 열을 고려하고 있다고 가정할게요.보라색 네모 부분이 k번째 열입니다.이 때 고려할 수 있는 경우의 가짓수는 3가지입니다.1. (k열 0행)을 선택한다.2. (k열 1행)을 선택한다.3. 해당 스티커를 선택하지 않는다. 각 경우들의 동작은 잠시 미뤄두고 이번엔 k + 1번째 열을 고려해볼게요.초록색으로 ..

[C++] 백준 14500: 테트로미노

안녕하세요 오늘 풀어볼 문제는 테트로미노 입니다.https://www.acmicpc.net/problem/14500 테트로미노는 문제는 기본 DFS에서 몇 가지 더 고려해줘야 하는 부분이 있습니다.1. T자형 테트로미노2. 가지치기 1. T자형 테트로미노T자형 테트로미노는 T처럼 생긴 테트로미노에요. 다른 모양의 테트로미노는 DFS로 검사할 수 있지만 T자형은 그럴 수 없습니다.왜일까요? 각 테트로미노의 탐색 방향을 표시해봤어요.다른 모양의 테트로미노들은 모두 한 붓 그리기가 가능합니다.즉, 하나의 분기를 하나의 경우로 취급하는 DFS로 탐색하기 적절하다는 뜻이지요.이건 대칭이나 회전을 시켜도 동일합니다. 그런데 T자형 테트로미노는 2번 이상 분기하지 않으면 탐색이 불가능합니다.그래서 각 좌표에서 T자형..

[C++] 백준 9019: DSLR

안녕하세요 오늘 풀어볼 문제는 백준 DSLR 입니다.https://www.acmicpc.net/problem/9019 저는 문제를 두 가지 작은 문제로 나누었어요.1. 각 연산(DSLR)의 구현2. 실제 연산을 수행하면서 최소한의 연산 횟수를 탐색 1. 각 연산(DSLR)의 구현이 문제는 어렵지 않습니다.// Dint d = (n * 2) % 10000;// Sint s = (n - 1) >= 0 ? (n - 1) : 9999;// Lint l = (n % 1000) * 10 + (n / 1000);// Rint r = (n % 10) * 1000 + (n / 10); 2. 실제 연산을 수행하면서 최소한의 연산 횟수를 탐색DFS로 접근을 해볼게요.1000을 1로 만드는 경우는 'RRR'과 'L' 두 가지..

[C++] 백준 30804: 과일 탕후루

안녕하세요 오늘 풀어볼 문제는 백준 과일 탕후루 입니다.https://www.acmicpc.net/problem/30804 처음 문제를 봤을 때는 두 가지 풀이를 떠올렸어요.1. dequeue를 사용해 일일이 경우의 수를 검사2. n부터 시작하는 탕후루 중 가장 긴 경우들을 추출 두 경우 모두 O(n^2)의 시간 복잡도를 가지기 때문에 그다지 좋은 생각은 아니었네요. 이 문제는 투포인터 문제입니다.투포인터란 수열의 시작과 끝 인덱스를 사용해 O(n)로 조건에 부합하며 연속된 수열을 검사하는 알고리즘이에요. 문제에서도 전형적인 투포인터 구현을 따랐습니다.수열이 조건을 만족하는 중이거나 만족하지 못했다면 수열의 길이를 늘이고if (cnt 조건을 만족하지 못했다면 수열의 길이를 줄였습니다.else l++;..

[C++] 백준 18111: 마인크래프트

안녕하세요. 오늘 풀어볼 문제는 백준 마인크래프트 입니다.https://www.acmicpc.net/problem/18111 마인크래프트는 구현 문제에요.줄글로는 직관적이지만 막상 소스 코드로 옮기려면 여러가지로 고려해야 할 것들이 있습니다. 마인크래프트라는 게임을 모른다면 줄글을 이해하는데도 시간이 걸릴 수 있겠네요. DP로 해결해야 하나? 라는 생각이 들 수도 있지만 각 원소가 서로 연관이 없고 높이끼리도 독립적이기 때문에 그럴 필요는 없습니다. 모든 높이 h애 대해 h를 만들기 위해 설치해야 할 블럭의 개수, 제거해야할 블럭의 개수를 구하면 h를 만들기 위한 시간도 알 수 있습니다. h를 만들기 위해 설치해야 할 블럭의 개수는 모든 원소에 대해 아래 라인을 수행하면 얻을 수 있습니다.if (map[..

[C++] 백준 1874: 스택 수열

안녕하세요. 오늘 풀어볼 문제는 스택 수열입니다.https://www.acmicpc.net/problem/1874 직관적으로 이해는 되지만 막상 구현할 때 멈칫하게 되는 문제에요.저는 배열로 간단한 스택을 만들어 사용했지만 stl을 사용하셔도 무방합니다. 문제에서 중요한 부분만 짚어 보겠습니다. 1. NO를 출력하는 조건NO를 출력하는 조건을 한 마디로 설명하자면'이미 버린 수를 뽑는 경우' 입니다. 스택에서 입력된 수를 뽑을 때는 '입력된 수까지 채운 다음 pop' 하거나, '입력된 수가 나올 때까지 pop' 해야 합니다.아래 코드에서는 항상 스택을 채우는 작업 다음에 빼는 작업을 하기 때문에 '입력된 수가 나올 때까지 pop'만 고려해주면 되겠죠. 그런데 만약 스택의 top이 입력된 수보다 작다면 이..

[C++] 백준 11053: 구간 합 구하기 5

안녕하세요. 오늘 풀어볼 문제는 백준 구간합 구하기 5입니다.https://www.acmicpc.net/problem/11660 이 문제는 구간 합 구하기 4의 심화버전이에요.수행하는 기능은 간단하지만 테스트 케이스가 1개 이상이기 때문에 dp를 사용해야 합니다. 문제에서는 입력이 2차원 배열으로 주어지는데요,각 행마다 dp를 적용하면 같은 x 값을 가지는 행들에서의 합을 구할 수 있겠죠.그 합을 구하는 행의 범위에서 모두 더하면 구간 합을 구할 수 있습니다.dp 배열은 0번부터 i번까지 원소들의 합으로 정의합니다.만약 2번부터 5번까지의 합이 알고 싶다면 dp[5] - dp[1]로 구할 수 있어요.dp[2]가 아닌 dp[1]을 빼는 이유는 dp[2]의 값도 포함되어야 하기 때문입니다. #include ..

[C++] 백준 15663: N과 M (9)

안녕하세요. 오늘 풀어볼 문제는 백준 N과 M (9)입니다.https://www.acmicpc.net/problem/15663 N과 M은 백준에서 아주 유명한 시리즈 문제입니다.이 시리즈는 모두 N개의 수 중에서 M개를 골라 수열을 출력하는 형식인데요,그 중에서도 이 아홉 번째 문제는 은근 까다로운 조건을 요구해서 유난히 정답률이 낮습니다. 우선 N과 M은 기본적으로 재귀를 통해서 해결하는 문제에요. 입력 받은 각 수에 대해서1. 해당 수를 사용했는지 체크해주고2. 정답 배열에 해당 수를 넣어주고3. 다음 깊이에 대해 재귀를 호출하고4. 해당 수를 사용하지 않는다고 체크해주면 됩니다. Base case는 깊이가 M과 같을 때 정답 배열을 모두 출력해주면 돼요. N과 M (9)에서는 중복된 수가 입력으로 ..