题目描述
玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串(2=<N<=13),该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1。
输入描述
第一行输入N,第二行输入N个数字,只包含0,1,2
输出描述
无
示例:
输入
5
02120
5
02120
输出
1
1
分析
博主之前有一篇“玛雅人的密码”文章,这道题与那道题是一样的,故这里只是提一下简单的思路,具体的分析读者可以参考博主之前的文章。
这道题可以使用BFS搜索来做,使用STL的queue作为搜索队列,使用map记录每一个新的字符串需要经过多少次转换。另外需要写一个字符串移位的函数,每次只移动一位,每次移位后都需要判断是否符合题意。若不符合题意,将新的字符串放入队列中,直到队列为空。另外,只有一种情况会输出-1,就是数字不够的时候,这需要在输入的时候就进行判断。最后,在输出时一定要注意格式,每一个输出后都需要换行,不然会返回答案错误。
AC代码如下:
#include<iostream>
#include<map>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
map<string, int> msi;
queue<string> que;
int possible(string str)//判断是否有解
{
int c[3] = {0};
int length = str.length();
for(int i = 0; i < length; ++i)
{
//记录字符0,1,2的个数,这个技巧很常见,需要掌握
++c[str[i]-'0'];
}
//数字不够是导致这道题无解的唯一原因
if(c[0] == 0 || c[1] == 0 || c[2] < 2)
{
return -1;
}
return 0;
}
bool judge(string str)//判断是否是解
{
if(str.find("2012") == -1)//字符串中不包含目标子串
{
return false;
}
return true;
}
string myswap(string str, int i)//字符移位
{
string temp = str;
temp[i] = str[i+1];
temp[i+1] = str[i];
return temp;
}
int main(void)
{
int n;
L: while(cin >> n)//标号用于goto跳出多重循环
{
string str;
cin >> str;
if(possible(str) == -1)//首先判断是否有解
{
cout << -1 << endl;
}
else
{
msi.clear();//将map清空
//STL的queue没有提供clear方法,不过我们应该有很多方法清空一个队列
//这个方法应该是清空队列最快的方法
//将非空队列和空队列进行交换,利用了泛型swap方法
queue<string> empty;
swap(empty, que);
que.push(str);//将原始字符串压入队列
msi[str] = 0;//map记录移位次数,这种语法也可以在map中插入元素
string temp;
while(!que.empty())//队列非空
{
temp = que.front();//取出队列首元素的方法是front
que.pop();//将队列首元素移除
if(judge(temp))//判断是否符合条件
{
cout << msi[temp] << endl;
break;//进入下一个输入
}
else//不符合条件
{
string newstr;
for(int i = 0; i < n-1; ++i)//不断移位
{
newstr = myswap(temp, i);
if(msi.find(newstr) != msi.end())//不是新字符串
{
if(judge(newstr))//判断是否符合条件
{
cout << msi[newstr] << endl;
goto L;//进入下一个输入
}
}
else//是新字符串
{
//在map中插入新元素,并且移位次数加1
msi[newstr] = msi[temp] + 1;
if(judge(newstr))//判断是否符合条件
{
cout << msi[newstr] << endl;
goto L;//进入下一个输入
}
else//不符合条件的新字符串就压入队列中
{
que.push(newstr);
}
}
}
}
}
}
}
return 0;
}