acwing 3385. 玛雅人的密码
题目描述
玛雅人有一种密码,如果字符串中出现连续的 2012 四个数字就能解开密码。
给定一个长度为 N 的字符串,该字符串中只含有 0,1,2 三种数字。
可以对该字符串进行移位操作,每次操作可选取相邻的两个数字交换彼此位置。
请问这个字符串要移位几次才能解开密码。
例如 02120 经过一次移位,可以得到 20120,01220,02210,02102,其中 20120 符合要求,因此输出为 11。
如果无论移位多少次都解不开密码,输出 −1。
输入格式
第一行包含一个整数 NN,表示字符串的长度。
第二行包含一个由 0,1,2 组成的,长度为 NN 的字符串。
输出格式
若可以解出密码,则输出最少的移位次数;否则输出 −1。
数据范围
2≤N≤13
输入样例:
5 02120
输出样例:
1
bfs
分析
和这个题一样
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<unordered_map>
using namespace std;
bool is_have(string a, string b)
{
for(int i = 0; i < a.size(); i++)
{
int k = i;
int j = 0;
while( k < a.size() && j < b.size() && a[k] == b[j] )
{
k++;
j++;
}
if(j == b.size()) return true;
}
return false;
}
int bfs(string start)
{
unordered_map<string, int> d; // 表示到某个状态的距离
d[start] = 0;
// bfs 常规操作
queue<string> q;
q.push(start);
while(q.size())
{
string t = q.front();
q.pop();
int dis = d[t];
if(t.find("2012") != -1) return d[t];
// if(is_have(t, "2012")) return d[t];
string next;
for(int i = 0; i < t.size() - 1; i++)
{
swap(t[i], t[i+1]);
if(!d.count(t))
{
d[t] = dis + 1;
q.push(t);
}
swap(t[i], t[i+1]);
}
}
return -1;
}
int main()
{
int n;
string start;
cin >> n;
cin >> start;
cout << bfs(start) << endl;
return 0;
}