1. 程式人生 > >瑪雅人的密碼

瑪雅人的密碼

題目描述

瑪雅人有一種密碼,如果字串中出現連續的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;//大功告成
}