1482 玛雅人的密码
http://ac.jobdu.com/problem.php?pid=1482
http://ac.jobdu.com/oldexamset.php
玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2<= N <=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1。
思路:这题明显数据量不大,可以用bfs做。但是有一些地方需要注意。
1.这个bfs和之前写过的开密码锁的类似,搜索的方向,也就是状态转移有好多种,需要依次遍历。
2.这个的位数有13位,不能开一个10E13的数组,会超空间。因为每个数都是0 1 2,所以可以状态压缩,将三进制转变成十进制,也可以用map来存,使用find(),如果找不到,就返回map.end()这个功能。
3.遇到输入string的题,就直接cin吧,而且cin string类型的时候需要include string。
代码如下:
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <stdio.h>
#include <string>
using namespace std;
string s;
map<string, int> mapp;
int ans;
struct state{
string s;
//int flag = 1;
int step;
state(string s1, int st){
s = s1; step = st;
}
};
int isOK(string s){
for (int i = 3; i < s.length(); i++){
if (s[i - 3] == '2' && s[i - 2] == '0' && s[i - 1] == '1' && s[i] == '2')
return 1;
}
return 0;
}
void bfs(state start){
queue<state> q;
q.push(start);
while (!q.empty()){
state first = q.front();
mapp[first.s] = 1;
q.pop();
if (isOK(first.s) == 1){
ans = first.step;
break;
}
for (int i = 1; i < first.s.length(); i++){
string temp = first.s;
char c = temp[i - 1]; temp[i - 1] = temp[i]; temp[i] = c;
if (mapp.find(temp) == mapp.end()){
mapp[temp] = 1;
q.push(state(temp, first.step+1));
}
}
}
}
int main(){
int n;
while (scanf("%d", &n) != EOF){
ans = -1;
mapp.clear();
//scanf("%s", s);
cin >> s; //遇到输入string类型的,就直接cin吧
if (s.length() < 4) {
printf("-1\n");
continue;
}
bfs(state(s, 0));
printf("%d\n", ans);
}
return 0;
}