아까 merge sort 문제 풀고 나서
가볍게 도전해 볼 문제로 고른 이번 문제...
그러지 말았어야 했어요.
입력받은 숫자를
1. 3으로 나누어 떨어진다면 3으로 나누거나
2. 2로 나누어 떨어진다면 2로 나누거나
3. 1을 뺀다.
위 세 과정 중 하나를 반복하여 결과적으로 숫자를 1로 만들고,
그러기까지 필요한 총 연산 수의 최솟값을 출력하는 문제입니다.
되게 단순한 문제인 줄 알았는데 그게 아니더라구요.
3 또는 2로 나누어 떨어질 때도, 1을 빼는 쪽이 결과적으로 더 연산이 적게 필요할 수도 있어요.
예를 들어 10은 10-5-4-2-1, 총 연산수 4번이지만
10-9-3-1, 즉 1을 빼는 쪽으로 시작하면 총 연산수가 3번입니다.
늘 그렇듯 잘 모를 때는 백준의 질문 검색을 이용합니다...
알고리즘 분류는 다이나믹 프로그래밍, 그 중에서도 BFS (Breadth First Search; 너비 우선 탐색) 으로 해결하는 문제라고 합니다.
이론을 분명 배웠을텐데 기억이 안 나서 바로 공부했어요.
BFS를 이용한 최소 거리 찾기는 지금도 이해를 잘 못했어요... ㅠㅠ
문제 풀면서 가장 많은 도움을 받은 질문글은 아래와 같습니다.
이후로 약 3~4시간 머리 싸매고 고민하였으나 답은 나오지 않았고...
결국 이 블로그에서 내용을 참고했어요.
결과적으로 제가 생각했던 depth를 구분하여 푸는 방법은 queue를 두 개 사용하셨더라구요.
#include <iostream>
#include <queue>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int input;
cin >> input;
bool visited[input+1];
for (int i = 0; i <= input; i++)
visited[i] = false;
queue<int> before;
queue<int> after;
before.push(input);
int count = 0;
while (!before.empty())
{
int num = before.front();
before.pop();
if (num == 1)
{
cout << count << '\n';
break;
}
if (num > 1 && !visited[num])
{
visited[num] = true;
if (num % 3 == 0)
after.push(num/3);
if (num % 2 == 0)
after.push(num/2);
after.push(num-1);
}
if(before.empty())
{
before = after;
while (!after.empty())
after.pop();
count++;
}
}
return 0;
}
블로그 원 작성자분은 Java로 작성하셨는데, 저는 C++로 베껴왔습니다.
내용은 어렴풋이 이해가 되긴 하는데 제가 작성한 코드가 아니다 보니 조금 더 시도를 해 봐야 할 것 같아요.
일단 글은 올려놓고 나중에 추가 보충 설명 더 하는걸로...
'알고리즘, 문제해결 > 알고리즘 문제풀이' 카테고리의 다른 글
[백준 1339번] 단어 수학 (0) | 2020.11.06 |
---|---|
[백준 17497번] 계산기 (0) | 2020.11.05 |
[백준 1202번] 보석 도둑 (0) | 2020.10.12 |
[백준 2751번] 수 정렬하기 2 (0) | 2020.05.08 |
[백준 10989번] 수 정렬하기 3 (0) | 2020.05.06 |
댓글