문제
영선이는 매우 기쁘기 때문에, 효빈이에게 스마일 이모티콘을 S개 보내려고 한다.
영선이는 이미 화면에 이모티콘 1개를 입력했다. 이제, 다음과 같은 3가지 연산만 사용해서 이모티콘을 S개 만들어 보려고 한다.
- 화면에 있는 이모티콘을 모두 복사해서 클립보드에 저장한다.
- 클립보드에 있는 모든 이모티콘을 화면에 붙여넣기 한다.
- 화면에 있는 이모티콘 중 하나를 삭제한다.
모든 연산은 1초가 걸린다. 또, 클립보드에 이모티콘을 복사하면 이전에 클립보드에 있던 내용은 덮어쓰기가 된다. 클립보드가 비어있는 상태에는 붙여넣기를 할 수 없으며, 일부만 클립보드에 복사할 수는 없다. 또한, 클립보드에 있는 이모티콘 중 일부를 삭제할 수 없다. 화면에 이모티콘을 붙여넣기 하면, 클립보드에 있는 이모티콘의 개수가 화면에 추가된다.
영선이가 S개의 이모티콘을 화면에 만드는데 걸리는 시간의 최솟값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 S (2 <= S <= 1000) 가 주어진다.
출력
첫째 줄에 이모티콘을 S개 만들기 위해 필요한 시간의 최솟값을 출력한다.
풀이
상태는 (클립보드 개수, 화면 개수) 두 가지로 잡으면 된다. 각 상태에서 가능한 연산은 현재 화면 전체 복사, 클립보드 붙여넣기, 하나 삭제 세 가지다.
모든 연산 비용이 1이므로 BFS를 쓰면 처음 도달한 시간이 곧 최소 시간이다. 방문 배열을 visited[clipboard][screen]으로 두고 중복 상태를 막아 주면 된다.
코드에서는 시작 상태를 (screen = 1, clipboard = 0)으로 두고 세 연산을 그대로 큐에 넣는다. 복사 연산은 화면의 개수를 통째로 클립보드에 옮기는 것이고, 붙여넣기는 screen + clipboard, 삭제는 screen - 1 상태로 이동하는 식이다. 각 상태를 한 번만 방문하게 만들면 같은 상황을 더 비싸게 다시 탐색할 필요가 없다.
또한 화면이나 클립보드 개수는 정답 범위를 크게 벗어날 필요가 없어서 1000까지만 관리해도 충분하다. BFS가 S에 처음 도달하는 순간의 연산 횟수가 곧 정답이 된다.
코드
#include <iostream>
#include <queue>
using namespace std;
bool visited[1001][1001];
void solve(int S) {
queue<pair<int , pair<int, int>>> q;
q.push(make_pair(0, make_pair(1, 0)));
visited[0][1] = true;
while (!q.empty()) {
int clipboard = q.front().first;
int sum = q.front().second.first;
int cnt = q.front().second.second;
q.pop();
if (sum == S) {
cout << cnt << '\n';
return;
}
if (sum > 0 && sum <= 1000 && !visited[sum][sum]) {
visited[sum][sum] = true;
q.push(make_pair(sum, make_pair(sum, cnt + 1)));
}
if (clipboard > 0 && sum + clipboard <= 1000 && !visited[clipboard][sum + clipboard]) {
visited[clipboard][sum + clipboard] = true;
q.push(make_pair(clipboard, make_pair(sum + clipboard, cnt + 1)));
}
if (sum > 0 && !visited[clipboard][sum - 1]) {
visited[clipboard][sum - 1] = true;
q.push(make_pair(clipboard, make_pair(sum - 1, cnt + 1)));
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int S = 0;
cin >> S;
solve(S);
return 0;
}복잡도
- 시간 복잡도:
- 공간 복잡도:
마무리
직관적으로는 DP 같지만, 상태 그래프로 보면 BFS가 훨씬 자연스럽다. 화면 수와 클립보드 수를 같이 보는 것이 핵심이다.
