题目描述:玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2=<N<=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1。
解题思路:BFS(详情见代码)
代码:
#include <iostream>
#include <queue>
#include <set>
#include <string>
using namespace std;
const string SS = "2012";
struct Status{
string str;
int times;
Status(){}
Status(string s,int t):str(s),times(t){}
bool operator< (Status y) const{
return times>y.times;
}
};
void Solve(string str){
Status item;
set<string> mySet; // 判断某一键值是否在set出现过。count() 用来查找set中某个某个键值出现的次数(0 或 1)
priority_queue<Status> myQueue; // 根据times, 从小到大排列Status
myQueue.push(Status(str,0));
while(!myQueue.empty()){
item = myQueue.top();
myQueue.pop();
if(item.str.find(SS)!=string::npos){ // 判断是否包含子串
cout<<item.times<<endl;
return;
}
string temp0 = item.str,temp;
int len = temp0.size();
for(int i=0;i<len-1;i++){
// 进行移位操作
temp = temp0.substr(0,i) + temp0.substr(i+1,1) + temp0.substr(i,1) + temp0.substr(i+2);
// 判断新状态是否是有效状态
if(mySet.count(temp)==0){
mySet.insert(temp);
myQueue.push(Status(temp, item.times+1));
}
}
}
cout<<-1<<endl;
}
int main() {
int N;
string str;
while(cin>>N>>str){
Solve(str);
}
return 0;
}