문제 : 백준 1327 소트 게임 🎮
난이도 : 골드 5
1️⃣ 소트 게임은 1부터 N까지 정수로 이루어진 N자리의 순열을 이용한다.
2️⃣ 어떤 수를 뒤집으면, 그 수부터 오른쪽으로 K개의 수를 뒤집어야 한다.
3️⃣ 반드시 K개의 수를 뒤집어야하기 때문에, 처음 상태에서 2나 1을 선택하는 것은 불가능하다. (2 ≤ K ≤ N ≤ 8)
4️⃣ 입력으로 들어온 순열을 오름차순으로 만들려고 한다.
5️⃣ 게임을 최대한 빨리 끝내고 싶을 때, 수를 최소 몇 개 선택해야 하는지 구해보자.
KEY POINT
1) 입력받은 문자열 중에서 하나씩 선택하여 K개의 수를 뒤집어 보면서, 오름차순이 되는 경우가 있는지를 확인해본다.
2) 이때, 최소의 개수를 선택하는지를 확인해야 하므로 BFS를 사용하여 살펴본다.
3) 그리고 Map을 사용하여 이미 해당 문자열 방문 여부를 표시해준다.
- 이전에 해당 문자열과 동일한 문자열을 방문한 경우, 최소 방문이기 때문에 해당 문자열은 최소를 만족하지 않아서 더이상 탐색을 하지 않아도 된다.
이때, 중요한 점은 숫자를 문자열로 입력받는다는 점이다!! 🔥
왜냐하면, 숫자를 문자열로 입력받으면 substr()함수를 사용하여 원하는 문자열의 길이만큼 잘라서 reverse()함수로 뒤집을 수 있기 때문이다!!
char nums;
string numbers;
for(int i=0; i<N; i++){
cin >> nums;
numbers += nums;
}
string origin_numbers;
origin_numbers = numbers;
sort(numbers.begin(), numbers.end()); //구하고자 하는 오름차순 정렬
for(int i=0; i<=N-K; i++){
string num1 = here.substr(0,i);
string num2 = here.substr(i, K);
reverse(num2.begin(), num2.end());
string num3 = here.substr(K+i,N);
que.push({num1+num2+num3,depth+1});
}
map<string, bool> map1;
queue<pair<string,int>> que;
que.push({origin_numbers,0});
while(!que.empty()){
string here = que.front().first;
int depth = que.front().second;
if(here == numbers){
ans = depth;
break;
}
que.pop();
if(map1[here] != true){
for(int i=0; i<=N-K; i++){
string num1 = here.substr(0,i);
string num2 = here.substr(i, K);
reverse(num2.begin(), num2.end());
string num3 = here.substr(K+i,N);
que.push({num1+num2+num3,depth+1});
}
map1[here] = true;
}
}
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
int main() {
std::ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int N = 0, K =0;
char nums;
string numbers;
string origin_numbers;
map<string, bool> map1;
int ans = -1;
cin>>N>>K;
for(int i=0; i<N; i++){
cin >> nums;
numbers += nums;
}
origin_numbers = numbers;
sort(numbers.begin(), numbers.end()); //구하고자 하는 오름차순 정렬
queue<pair<string,int>> que;
que.push({origin_numbers,0});
while(!que.empty()){
string here = que.front().first;
int depth = que.front().second;
if(here == numbers){
ans = depth;
break;
}
que.pop();
if(map1[here] != true){
for(int i=0; i<=N-K; i++){
string num1 = here.substr(0,i);
string num2 = here.substr(i, K);
reverse(num2.begin(), num2.end());
string num3 = here.substr(K+i,N);
que.push({num1+num2+num3,depth+1});
}
map1[here] = true;
}
}
cout<<ans<<"\n";
}