玛雅人的密码

这篇博客探讨了玛雅密码的解锁问题,其中关键在于寻找包含连续2012序列的字符串。通过使用广度优先搜索(BFS)策略,可以在给定长度限制(2=<N<=13)且仅包含0,1,2的字符串中,找出最少的移位次数来形成2012序列。若无法形成,则输出-1。博主提醒,解决此类问题时要注意空间复杂度,避免无效重复计算。" 132371562,5694251,Android Framework层按键事件处理详解,"['Android开发', '框架层', '按键事件处理', ' RK3568', '应用开发']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2=<N<=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1

分析:想了半天才想到利用BFS求解最快可行解,13个数字并行找,找到第一个满足条件的输出。注意需要特判根本没有2012的,由于BFS消耗的空间比较大,需要注意利用map记录一下查找过的数字,同时只要朝着一个方向找就行。

代码:

/*DEBUG方法:输出,试数调错
找数据范围极限判断特例
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
    char s[14];
    int num;
};
 
map<ll,int>ma;
const int INF = 0x3f3f3f3f;
bool judge(node x)
{
    int len = strlen(x.s);
    for(int i = 0; i < len - 3; i++)
    {
        if(x.s[i] == '2' && x.s[i + 1] == '0' && x.s[i + 2] == '1' && x.s[i + 3] == '2')
        {
            return true;
        }
    }
    return false;
}
ll cal(node x)
{
    ll sum = 0;
    for(int i = 0; i < strlen(x.s); i++)
    {
        sum = sum * 10 + x.s[i] - '0';
    }
    return sum;
}
void bfs()
{
    ma.clear();
    queue<node>que;
    while(!que.empty())
    {
        que.pop();
    }
    node x;
    char s[14];
    scanf("%s",s);
    if(strlen(s) < 4)
    {
        printf("-1\n");
        return ;
    }
    int cnt0 = 0,cnt1 = 0,cnt2 = 0;
    for(int i = 0; i < strlen(s); i++)
    {
        if(s[i] == '0')
        {
            cnt0++;
        }
        else if(s[i] == '1')
        {
            cnt1++;
        }
        else
        {
            cnt2++;
        }
    }
    if(!(cnt2 >= 2 && cnt1 >= 1 && cnt0 >= 0))
    {
        printf("-1\n");
        return;
    }
    strcpy(x.s,s);
    x.num = 0;
    que.push(x);
    ma[cal(x)] = 1;
    int len = strlen(s);
    while(!que.empty())
    {
        node top = que.front();
        ma[cal(top)] = 1;
       // printf("%s\n",top.s);
        que.pop();
        if(judge(top))
        {
            printf("%d\n",top.num);
            return;
        }
        for(int i = 0; i < len; i++)
        {
            node tmp;
            if(!i)
            {
                char stmp[14];
                strcpy(stmp,top.s);
                swap(stmp[i],stmp[i + 1]);
                strcpy(tmp.s,stmp);
                tmp.num = top.num + 1;
                if(!ma[cal(tmp)])
                {
                    que.push(tmp);
                }
            }
            else if(i == len - 1)
            {
                char stmp[14];
                strcpy(stmp,top.s);
                swap(stmp[i - 1],stmp[i]);
                strcpy(tmp.s,stmp);
                tmp.num = top.num + 1;
                que.push(tmp);
                if(!ma[cal(tmp)])
                {
                    que.push(tmp);
                }
            }
            else
            {
                node tmpl,tmpr;
                char stmpl[14],stmpr[14];
                //strcpy(stmpl,top.s);
                strcpy(stmpr,top.s);
                //swap(stmpl[i],stmpl[i - 1]);
                swap(stmpr[i],stmpr[i + 1]);
                //strcpy(tmpl.s,stmpl);
                strcpy(tmpr.s,stmpr);
                //tmpl.num = top.num + 1;
                tmpr.num = top.num + 1;
                //que.push(tmpl);
                que.push(tmpr);
                /*if(!ma[cal(tmpl)])
                {
                    que.push(tmpl);
                }*/
                if(!ma[cal(tmpr)])
                {
                    que.push(tmpr);
                }
            }
        }
    }
    printf("-1\n");
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        bfs();
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值