일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- BFS
- 유니온 파인드
- 우선순위 큐
- 스택
- 투 포인터
- XR Interaction Toolkit
- 문자열
- 자료구조
- 다익스트라
- ue5
- DFS
- 알고리즘
- 수학
- 그래프
- 백트래킹
- 트리
- 구현
- 유니티
- 다이나믹 프로그래밍
- 브루트포스
- Unreal Engine 5
- 재귀
- 시뮬레이션
- 누적 합
- 정렬
- 백준
- 그리디 알고리즘
- Team Fortress 2
- c++
- VR
- Today
- Total
1일1알
백준 2502번 떡 먹는 호랑이 C++ 본문
조금 특이한? dp 문제이다.
우선 점화식을 세울 때 생각한 것은 어떤 날이든 첫째 날과 둘째 날의 떡의 개수로 분해할 수 있다는 것이다.
예를 들어 5번째 날은 3번째 날 + 4번째 날이고, 3번째 날은 1번째 날 + 2번째 날, 4번째 날은 2번째 날 + 3번째 날.. 이런 식으로 밑으로 내려가면서 최종적으론 1번째 날과 2번째 날의 떡의 개수의 조합으로 나타낼 수 있다.
그림으로 나타내면 이런 식으로, 5번째 날은 최종적으로 2 * 1번째 날, 3* 2번째 날의 떡의 개수로 나타낼 수 있다.
하지만 숫자가 주어질 때마다 이런 식으로 계속 분해하면 시간이 오래 걸리기 때문에 bottom-up 방식으로 해결하기로 생각했다.
pair을 이용하여 dp배열을 만들었는데, 첫 번째 원소는 첫 번째 날 떡의 개수의 수량이고, 두 번째 원소는 두 번째 날 떡의 개수의 수량이다.
dp[1]은 첫 번째 날이므로 첫 번째 날 떡의 개수를 1개만 가지고 있기 때문에 {1, 0}이고,
dp[2]는 두 번째 날이므로 두 번째 날 떡의 개수를 1개만 가지고 있기 때문에 {0 , 1} 이다.
dp[3]부터는 dp[3-2] + dp[3-1] 이기 때문에 {dp[3-2].first + dp[3-1].first , dp[3-2].second+dp[3-1].second} 로 구할 수 있다.
이것을 이용하여 만든 점화식은 dp[i] = { dp[i - 2].first + dp[i - 1].first, dp[i - 2].second + dp[i - 1].second } 이다.
이 식을 이용해서 dp[5]를 구하면 {2, 3}이 나온다. 위의 그림과 같은 결과가 나오는 것을 볼 수 있다.
이제 k를 이용하여 첫 번째 날의 떡의 개수와 두 번째 날 떡의 개수를 구해야 한다.
첫 번째 예제에서는 6일째에 41개를 줬다고 했다. dp[6]은 {3, 5} 이다.
첫째 날에 한 개를 줬다고 가정하면, 3 * 1 + 5 * 두 번째 날 떡의 개수 = 41 이 되어야 하는데, 두 번째 날 떡의 개수가 자연수가 나오지 않기 때문에 답이 될 수 없다.
첫째 날에 두 개를 줬다고 가정하면, 3 * 2 + 5 * 두 번째 날 떡의 개수 = 41이고, 여기서는 두 번째 날 떡의 개수가 7이 되기 때문에 답이 될 수 있다.
답은 여러 개가 될 수 있는데, 그중 아무거나 출력해도 된다고 하니 제일 먼저 나온 답을 출력하면 된다.
그러므로 첫 번째 예제의 정답은 첫째 날에는 2개, 둘째 날에는 7개를 준 경우이다.
두 번째 예제의 결과는 2, 26이 나왔는데 계산해보면 2, 26, 28, 54, 82, 136, 218이 되고, 정답 처리되었다.
#include <iostream>
#include <string>
#include <vector>
#include <math.h>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <math.h>
#include <set>
#include <unordered_set>
using namespace std;
typedef long long ll;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int d, k;
cin >> d >> k;
vector<pair<int, int>> dp(d + 1, { 0,0 });
dp[1] = { 1,0 };
dp[2] = { 0,1 };
for (int i = 3; i <= d; i++) {
dp[i] = { dp[i - 2].first + dp[i - 1].first,dp[i - 2].second + dp[i - 1].second };
}
int first = dp[d].first;
int second = dp[d].second;
int ans1 = 1;
while ((k - (first * ans1)) % second != 0) {
ans1++;
}
int ans2 = (k - (first * ans1)) / second;
cout << ans1 << "\n" << ans2;
};
'알고리즘' 카테고리의 다른 글
백준 2493번 탑 C++ (0) | 2021.11.07 |
---|---|
백준 2531번 회전 초밥 C++ (0) | 2021.11.06 |
백준 1759번 암호 만들기 C++ (0) | 2021.11.04 |
백준 12852번 1로 만들기 2 C++ (0) | 2021.11.03 |
백준 1926번 그림 C++ (0) | 2021.11.02 |