计算机历年考研复试上机题------玛雅人的密码

题目传送门
这道题是BFS(广度优先搜索)的一道变形题,但是他的核心算法也是BFS的那一套。这种题比较具有代表性。
有请题目:

题目描述
玛雅人有一种密码,如果字符串中出现连续的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

这种类型的题,我看到以后我的第一反应就是要遍历出每一种情况(当然如果你有更好的方案的话,欢迎留言交流,共同学习)。既然我们要遍历出每一种情况的话搜索就成了一个很好的选择。
我们注意一下题目中的信息:
①字符串的长度在 [2,13]之间数据并不大,我们用搜索的方式并不会出现超时的情况。
②存在不出现2012的情况!(我在程序中并没有对于这种情况进行优化,如果大家想对程序进行优化的话可以通过这个方面,ps:检查字符串中是否有俩个‘2’,‘1’,‘0’,存在的话必定通过有限次交换可以出现2012字符串)

代码:

#include
#include
#include
#include
using namespace std;

struct StrNodeStep {
    StrNodeStep(string a,int s)
        :str(a)
        ,step(s)
    {}
    string str;
    int step;
};
//申请一个map来存储我们走过的节点
map<string, int> vis;
//交换函数
string swap(string str,int x,int y)
{
    char a = str[x];
    str[x] = str[y];
    str[y] = a;
    return str;
}
//检查当前字符串中是否有“2012”字符串
bool cheak(string str)
{
    if (str.size() <= 3)return false;
    for (int i=0; i<(str.size()-3); i++)
    {
        if (str[i] == '2'&&str[i+1] == '0'
            && str[i+2] == '1' && str[i+3] == '2')
            return true;
    }
    return false;
}
int bfs(string str,int num)
{
    //想队列
    StrNodeStep fri = StrNodeStep(str, 0);
    queue q;
    q.push(fri);
    while (!q.empty())
    {

        StrNodeStep node = q.front();
        //标记走过的节点
        vis[node.str] ++;
        //当前存在2012字符串
        if (cheak(node.str)) return node.step;
        q.pop();
        //记录当前步数
        int step = ++node.step;
        //遍历字符串相邻替换
        for (int i = 0; i < num-1; i++)
        {
            string s = swap(node.str, i, i + 1);
            if (vis.find(s)==vis.end())
            {
                StrNodeStep node = StrNodeStep(s, step);
                q.push(node);
            }
        }
    }
    return -1;
}
int main()
{
    int num;
    string str;
    while (cin >> num>>str)
    {
        vis.clear();
        cout << bfs( str,  num) << endl;
    }
    return 0;
}

你可能感兴趣的:(考研,广搜)