玛雅人的密码
原创
©著作权归作者所有:来自51CTO博客作者不想悲伤到天明的原创作品,请联系作者获取转载授权,否则将追究法律责任
题目描述
玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2=<N<=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1。
输入描述:
输入包含多组测试数据,每组测试数据由两行组成。
第一行为一个整数N,代表字符串的长度(2<=N<=13)。
第二行为一个仅由0、1、2组成的,长度为N的字符串。
输出描述:
对于每组测试数据,若可以解出密码,输出最少的移位次数;否则输出-1。
示例1
输入
复制
5
02120
输出
复制
1
思路: 自己用dfs写的只过了60%,看了看题解是用bfs 做的,真香! 首先将字符串 str 看做根节点,交换一次的字符串作为第二层,以此类推,直到出现有 "2012"的字符串,那么它的深度就是交换次数。
#include <iostream>
#include <map>
#include <queue>
#include <string>
using namespace std;
queue<string> q ;
map<string,int> m ;
int n ;
string str ;
string Swap(string s,int i ) {
char t ;
t = s[i] ;
s[i] = s[i+1] ;
s[i+1] = t ;
return s ;
}
bool check1(string str ) {
if(str.find("0")== string::npos )
return true ;
else if (str.find("1")== string::npos){
return true;
}
else if(str.find("2")== string::npos){
return true ;
}
return false ;
}
int bfs(string str) {
string newstr ;
m.clear() ;
while(!q.empty()) {
q.pop() ;
}
q.push(str) ;
m[str] = 0 ;
while(!q.empty()) {
str = q.front() ;
q.pop( ) ;
for(int i = 0 ; i<(int)str.length()-1 ; i++ ) {
newstr = Swap(str,i) ;
if(m.find(newstr) == m.end()) {//第一次出现
m[newstr] = m[str] + 1 ;
if(newstr.find("2012") !=string::npos) {
return m[newstr] ;
}
else {
q.push(newstr) ;
}
}
}
}
return -1 ;
}
int main() {
while(cin >>n){
cin >> str ;
if(n<4) { // 如果小于4一定组不成2012
cout<<"-1"<<endl ;
}
else if(check1(str)) {//特判
cout<<"-1"<<endl;
}
else {
if(str.find("2012") !=string::npos) {
cout<<"0"<<endl ; //如果根节点包含
}
else {
cout<<bfs(str)<<endl;
}
}
}
return 0 ;
}