瑪雅人的密碼
阿新 • • 發佈:2018-12-04
題目描述
瑪雅人有一種密碼,如果字串中出現連續的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
AC_CODE:
#include <stdio.h> #include <iostream> #include <map> #include <string> #include <queue> using namespace std; map<string, int> M;//M[str]表示str經歷的交換次數 queue<string> Q;//佇列,用於bfs string Swap(string str, int i) {//將字串i位與i+1位交換 string newStr = str; char tmp = newStr[i]; newStr[i] = newStr[i + 1]; newStr[i + 1] = tmp; return newStr; } bool Judge(string str) {//判斷字串中是否含有"2012" if (str.find("2012", 0) == string::npos) return false; else return true; } int BFS(string str) {//廣度優先搜尋 string newStr; M.clear();//清空map while (!Q.empty()) Q.pop();//清空佇列 Q.push(str);//初始字串作為起點放入佇列 M[str] = 0;//初始字串經歷的交換次數是0 while (!Q.empty()) { str = Q.front(); Q.pop();//取出隊首,存入str for (unsigned i = 0; i<str.size() - 1; i++)//嘗試進行一次交換 { newStr = Swap(str, i);//新字串由str交換i位和i+1位得到 if (M.find(newStr) == M.end())//如果這個字串沒出現過 { M[newStr] = M[str] + 1;//現在出現過了,且交換次數比他爹多1 if (Judge(newStr) == true) return M[newStr];//符合要求,收工 else Q.push(newStr);//不合要求,那繼續bfs,把它加入佇列 } else continue;//出現過的字串,不用進行處理 } } return -1;//遍歷完成,沒發現符合要求的字串,返回-1 } int main() { int n; string str; while (scanf("%d", &n) != EOF) { cin >> str;//讀取字串(前面讀取n好像沒啥用) if (Judge(str) == true) printf("0\n");//一開始就符合要求的話 else//初始字串不符合要求,那就bfs { int ans = BFS(str); printf("%d\n", ans); } } return 0;//大功告成 }