题目描述
玛雅人有一种密码,如果字符串中出现连续的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
题目个人理解:交换相邻的字符,02120交换一次是20120,01220,02210,02102,再将第一次交换后的结果再交换一次,20120交换后是02120,21020,20210,20102。所以需要记录每次交换后的结果,未找到时,在交换的基础上再进行交换,直至找到。
注:1,第二次交换02120已经测试过未出现,所以不需要再进行记录。
2,代码中使用队列queue进行保存交换后的字符串
3,代码中的pair是map中定义的方法,是将两种元素作为一种合成元素,添加方法有两种:pair<string,int>(“abc”,5)或make_pair(“abc”,5)
具体请看代码:
#include<iostream>
#include<string>
#include<queue>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
int changepassword(string str)
{
queue<pair<string, int>> index; //pair一个实用的小东西,可以将两个类型的元素绑在一起作为一个合成元素,不用定义结构体
index.push(make_pair(str, 0)); //make_pair访问元素的方法 ,或者pair<string,int>(str,0)
vector<string> visit;
visit.push_back(str);
while (!index.empty())
{
string temp = index.front().first; //pair的访问,first是string类型数据 ,second是第二个int数据
int count = index.front().second;
index.pop(); //出队先进的字符串
for (int i = 0; i < temp.length() ; i++)
{
if(i == 0){ //判断原始字符串是否有符合
if (str.find("2012") != string::npos)
return count;
}else{
string cur = temp;
swap(cur[i - 1], cur[i]);
if (cur.find("2012") != string::npos) //string的匹配,!=string:npos代表有匹配的数据
return count + 1;
vector<string>::iterator it = find(visit.begin(), visit.end(), cur); //vector查找数据cur并返回索引
if (it== visit.end()) // 是为了不将已经出现的再加入到数组中
{
index.push(make_pair(cur, count + 1));
visit.push_back(cur);
}
}
}
}
return -1;
}
int main()
{
int n;
while (cin >> n)
{
string str;
cin >> str;
cout << changepassword(str) << endl;
}
return 0;
}
本文介绍了一种通过字符串操作解密玛雅古老密码的算法。核心任务是在长度为N的字符串中,通过交换相邻字符来寻找2012序列,实现密码解锁。文章详细解析了使用队列和字符串匹配的解决方案,展示了如何通过递增交换次数来逼近目标序列。
846

被折叠的 条评论
为什么被折叠?



