神奇密码锁 BFS (枚举) 进位转换 memcmp

本文介绍了如何帮助小明破解四位数密码锁,详细解析了从一个数字到另一个数字的最小步数计算方法。问题中,密码仅包含1到9的数字,每次操作可以加1、减1或交换相邻数字。使用BFS算法,可以有效地找出从初始状态到达目标状态的最短路径。
摘要由CSDN通过智能技术生成

题目描述

 小明忘记了旅行箱上的密码,现在他想自己暴力弄出密码来,但他又想知道最从一个数字到另一个数字最少需要多少步,现在请你帮忙。

另外,小明的密码箱很奇怪,只有四位数,上面的数字只有1到9,每次只能让每位数加1或者减1。按常识我们可以知道从1到9只需要减1,从9到1只需要加1。此外,你还能交换相邻的两个数字。如1234可以在一步后变成2134,但不能变成4231。

输入

第一行有一个整数:T,代表有多少组测试数据。

接下来T行,每行有两个整数(都是四位数),第一个是初状态,第二个是目标状态。

输出

每组数据输出一个整数,占一行。

样例输入

2
1234 2144
1111 9999

样例输出

24
由题目可知:密码的转变一共有3种 上滑 下滑 移位。3者关系是平行的,这里题目只给出了起始状态和末尾状态,所以采用BFS进行枚举(枚举所有可能出现的变化)即可,可以说是黑箱操作。进位转换一直是我的弱项,加强学习下。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct node
{
    char s[10];
    int sum;
};
int ans=0;
char st[10],goal[10];
int vis[10005];
bool in(char s[])
{
    int re=(s[0]-'0')*1000+(s[1]-'0')*100+(s[2]-'0')*10+s[3]-'0';
    if(!vis[re]){
        vis[re]=true;
        return true;
    }
    return false;
}
void BFS()
{
    queue<node>que;
    node s;
    strcpy(s.s,st);
    s.sum=0;
    if(in(s.s))
        que.push(s);
    while(!que.empty()){
        s=que.front(); que.pop();
        if(strcmp(s.s,goal)==0)
            //memcmp(s.s,goal,sizeof(char)*4)==0
        {
             ans=s.sum ;
             return ;
        }
        for(int i=0;i<4;i++)
        { //密码设置 3种情况 上滑 下滑 移位
            //密码上滑
           char m=s.s[i];
           s.sum++;  //步数增加
           if(s.s[i]=='9') s.s[i]='1';
           else s.s[i]++;
           if(in(s.s)) //避免重复压入
                que.push(s);//压入队列进行判断
 
           //密码下滑
           s.s[i]=m;//还原该位数字
 
           if(s.s[i]=='1') s.s[i]='9';
           else s.s[i]--;
 
           if(in(s.s)) //避免重复压入
                que.push(s);//压入队列进行判断
 
 
           //密码位移
           s.s[i]=m;
           if(i<3){
           char mid=s.s[i+1];//发生密码位移
           s.s[i+1]=s.s[i];
           s.s[i]=mid;
           if(in(s.s))
             que.push(s);
 
           s.s[i]=m;
           s.s[i+1]=mid;//还原密码
           }
           s.sum--; //还原
        }
 
    }
}
int main()
{
    int icase;
    scanf("%d",&icase);
    while(icase--){
        scanf("%s%s",st,goal);
        memset(vis,0,sizeof(vis));
        BFS();
        printf("%d\n",ans);
 
    }
}
memcmp 在头文件cstring中, 是比较内存区域buf1和buf2的前count个字节。该函数是按 字节 比较的(函数原型:int memcmp(const void *buf1, const void *buf2, unsigned int count);)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值