두 개의 단어 begin, target과 단어의 집합 words가 있습니다. 아래와 같은 규칙을 이용하여 begin에서 target으로 변환하는 가장 짧은 변환 과정을 찾으려고 합니다.
1. 한 번에 한 개의 알파벳만 바꿀 수 있습니다. 2. words에 있는 단어로만 변환할 수 있습니다.
예를 들어 begin이 "hit", target가 "cog", words가 ["hot","dot","dog","lot","log","cog"]라면 "hit" -> "hot" -> "dot" -> "dog" -> "cog"와 같이 4단계를 거쳐 변환할 수 있습니다.
두 개의 단어 begin, target과 단어의 집합 words가 매개변수로 주어질 때, 최소 몇 단계의 과정을 거쳐 begin을 target으로 변환할 수 있는지 return 하도록 solution 함수를 작성해주세요.
직접 그림을 그려가면 DFS로 풀어야한다는 느낌이 직관적으로 들었다.
그러나 백트래킹의 조건을 고려하면서 해야하는 부분을 잊고있어서 시간이 조금 걸렸다.
앞으로 이런 문제를 만나면 두가지를 먼저 떠올리면서 시간을 단축해야겠다.
탐색하는 이유(조건)을 판단하는 함수를 작성한다.
위 문제에서는 서로 다른 문자의 개수가 1개일 때만 단어 변환이 가능한 조건이다.
탈출 조건 + (가지치기 조건) 판단하기
위 문제에서는 depth를 1씩 증가하면서 현재 단어가 target과 동일하다. (탈출조건)
또한 현재 depth가 현재까지 정답의 최소 depth보다 같거나 크면 탐색을 더이상 진행하지 않는다. (가지치기)
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int answer = 50; // 50개의 단어이므로 정답은 최대 50까지 가능하다.
bool visited[50];
bool check(string a,string b){
int cnt=0;
for(int i=0;i<a.length();i++){
if(a[i]!=b[i]){
cnt++;
}
}
return (cnt==1)?true :false;
}
void dfs(string begin,string target, vector<string>words, int depth){
// 현재 깊이가 (단계) answer보다 크면 탐색할 이유 x
if(depth>=answer){
return;
}
if(begin==target){
answer=min(answer,depth);
return;
}
for(int i=0;i<words.size();i++){
// 문자 변형이 가능하고 방문 x면 탐색 하기
if(check(begin,words[i])&&!visited[i]){
// 먼저 방문 체크 후 탐색 마친 후 다시 false로
visited[i]=true;
dfs(words[i],target,words,depth+1);
visited[i]=false;
}
}
}
int solution(string begin, string target, vector<string> words) {
// hit -> hot -> dot -> dog -> cog, hit -> hot -> lot -> log -> cog
// dfs, 백트래킹
// 우선 현재 단어와 다음 단어가 1글자의 차이인지 확인하는 함수를 만들자
// dfs 구현 시 target을 찾아도 뒤에 돌아가서 최솟값이 있는 경우가 있을 수 있으니 백트래킹도 같이 고려해야한다.
dfs(begin,target,words,0);
return (answer==50)?0:answer;
}