https://www.acmicpc.net/problem/12852
문제 요약
정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 입니다.
- X가 3으로 나누어 떨어지면, 3으로 나눕니다.
- X가 2로 나누어 떨어지면, 2로 나눕니다.
- 1을 뺍니다.
정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 합니다. 연산을 사용하는 횟수의 최솟값을 출력해야 합니다.
문제 풀이
1. 정수를 입력받습니다.
2. dfs 탐색을 하는데, 현재 개수가 저장해둔 개수보다 커지면 탐색을 리턴합니다. ( 첫 회차엔 1e9가 저장 되어 있음 )
3. 현재 숫자를 임시 배열에 저장하고 재귀 호출합니다. ( 3으로 나누어 떨어지면 3으로 나눠서, 2로도 나누어 떨어지며 2로 나눠서, 마지막으로 -1 )
4. 현재 만들어진 숫자가 1이면 현재 개수가 저장해둔 개수보다 작으면 저장하고 현재 숫자를 임시 배열에 추가 한 후 ( 아래 탐색 시작할때 현재 숫자를 추가하게 하였기 때문에 )
정답 배열을 임시 배열로 초기화 하여 리턴합니다.
5. 그렇게 마저 탐색하면서 가장 적은 개수와 그 정수들을 갱신합니다.
6. 탐색이 종료 되면 저장해 두었던 개수를 출력하고 정답 배열을 출력합니다.
주의할 점
아래 코드는 처음에 풀었던 코드입니다.
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
long long int n, ret = 1e9;
vector<long long int> v;
vector<long long int> ans;
vector<bool>visit;
void dfs(long long int x, long long int cnt)
{
v.push_back(x);
if (x == n)
{
if (cnt < ret)
{
ans.clear();
ret = min(cnt, ret);
ans = v;
}
return;
}
for (int i : {x * 3, x * 2, x + 1})
{
if (i > n)
{
continue;
}
if (!visit[i])
{
visit[i] = true;
dfs(i, cnt + 1);
visit[i] = false;
v.pop_back();
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n;
visit.resize(n + 1);
dfs(1, 0);
cout << ret << "\n";
for (int i = ans.size() - 1; i >= 0; i--)
{
cout << ans[i] << " ";
}
return 0;
}
1부터 n까지 탐색하는데 그 과정에서 반복문을 사용하였으나 시간초과가 발생하였습니다.
코드
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
long long int n, ret = 1e9;
vector<long long int> v;
vector<long long int> ans;
vector<bool>visit;
void dfs(long long int x, long long int cnt)
{
if (cnt > ret)
{
return;
}
if (x == 1)
{
if (cnt < ret)
{
ret = cnt;
// 현재 숫자 추가
v.push_back(x);
// 정답 경우의 수 저장
ans = v;
// 현재 숫자 삭제
v.pop_back();
}
return;
}
// 현재 숫자 추가
v.push_back(x);
if (x % 3 == 0)
{
dfs(x / 3, cnt + 1);
}
if (x % 2 == 0)
{
dfs(x / 2, cnt + 1);
}
dfs(x - 1, cnt + 1);
// 현재 숫자 삭제
v.pop_back();
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n;
visit.resize(n + 1);
dfs(n, 0);
cout << ret << "\n";
for (int i : ans)
{
cout << i << " ";
}
return 0;
}
반응형
예제 1
2
결과 1
예제 2
10
결과 2
'BAEKJOON > Backtracking' 카테고리의 다른 글
C++ / 13023 / ABCDE ( 백트래킹 ) (0) | 2025.01.01 |
---|---|
C++/ 26169 / 세 번 이내에 사과를 먹자 ( 백트래킹 ) (0) | 2024.12.31 |
C++ / 15651 / N 과 M ( 3 ) ( 백트래킹 ) (0) | 2024.12.01 |
C++ / 15650 / N과 M ( 2 ) ( 백트래킹 ) (0) | 2024.11.30 |
C++ / 15649 / N과 M ( 1 ) ( 백트래킹 ) (0) | 2024.11.29 |