问题 D: 神奇密码锁

今天小编又来跟新了 没办法A题目速度不高啊 本人还在处于训练状态请多多包涵

最近在训练DFS以及BFS  今天我来说说神奇密码锁问题 在做这个题目的过程中有思路 然后想上网找找 发现没有博客写关于这个问题 

所以我想讲讲我的解题思路

题目描述

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

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

输入

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

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

输出

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

样例输入

21234 21441111 9999

样例输出

24
首先在看这道题目时候我先没有考虑bfs以及dfs  我用一个3*3的二维数组来处理该位数字转换为其他位置上数字所需要的步数(包括互换),然后处理四次就可以了,我这样想过但是没有进行实现 感觉应该可以

好下面说一下DFS以及BFS的方法,我首先解释一下一个数变化有11种情况(每一位数字加减共8种  互换数字有三种  共11种)。我在分析的过程中把DFS排除了 因为在你往下走的过程中深度很大,你不知道跳出循环条件是什么 不过我今天听别人讲可以限制它的深度 如果在限制的深度中还是没有找到你要的答案 可以进一步加大深度直到你找到你的目标为止

至于BFS,其实思路是比较简单的 使用容器STL的队列 然后使用一个大小为10005的判断数组 如果走过为1 没有则为0 然后就是BFS的老套路了 先处理对头元素  取对头元素 (判断) 然后就是扩展 看是否走过 如果走过则跳过 如果没有则push 一直到找到目标为止

#include <iostream>
#include <algorithm>
#include <queue>
#include <stdio.h>
#include <cstring>
using namespace std;
int pangduan[11000]={0};
int bf(int y,int z)
{
    if (y+z==10) return 1;
    if (y+z==0) return 9;
    else return y+z;
}
typedef struct password
{
    int a,b,c,d,m;
}password;
int L[32]={1,0,0,0,-1,0,0,0,0,1,0,0,0,-1,0,0,0,0,1,0,0,0,-1,0,0,0,0,1,0,0,0,-1};
queue<password>Q;
int bfs(password,password);
int main()
{
    password W1,W2;
    int n,m;
    scanf("%d",&n);
    while(n--)
    {
        memset(pangduan,0,sizeof(pangduan));
        scanf("%d",&m);
        W1.d=m%10;m=m/10;W1.c=m%10;m=m/10;W1.b=m%10;W1.a=m/10;
        scanf("%d",&m);
        W2.d=m%10;m=m/10;W2.c=m%10;m=m/10;W2.b=m%10;W2.a=m/10;
        W1.m=W2.m=0;
        m=bfs(W1,W2);
        printf("%d\n",m);
    }
    return 0;
}
int bfs(password a,password b)
{
    Q.push(a);
    password c;
    int shu;
    while(!Q.empty())
    {
        c=Q.front();Q.pop();
        if(c.a==b.a&&c.b==b.b&&c.c==b.c&&c.d==b.d)
        {
            while(!Q.empty()) {Q.pop();}
            return c.m;
        }
        for(int i=0;i<8;i++)
        {
            a.a=bf(c.a,L[4*i]);a.b=bf(c.b,L[4*i+1]);
            a.c=bf(c.c,L[4*i+2]);a.d=bf(c.d,L[4*i+3]);
            a.m=c.m+1;
            shu=a.a*1000+a.b*100+a.c*10+a.d;
            if(pangduan[shu]) continue;
            else pangduan[shu]=1;
            Q.push(a);
        }
        a.m=c.m+1;
        a.a=c.b;a.b=c.a;a.c=c.c;a.d=c.d;shu=a.a*1000+a.b*100+a.c*10+a.d;if(!pangduan[shu]){pangduan[shu]=1;Q.push(a);}
        a.a=c.a;a.b=c.c;a.c=c.b;a.d=c.d;shu=a.a*1000+a.b*100+a.c*10+a.d;if(!pangduan[shu]){pangduan[shu]=1;Q.push(a);}
        a.a=c.a;a.b=c.b;a.c=c.d;a.d=c.c;shu=a.a*1000+a.b*100+a.c*10+a.d;if(!pangduan[shu]){pangduan[shu]=1;Q.push(a);}
    }
}
写得挺简洁的 但是当我交的时候就错了 因为发现时间超时了 做题时候没有考虑这个问题 然后我只能使用双向BFS 由于第一次敲代
简洁度有待加强

  
  
#include <iostream>
#include <algorithm>
#include <queue>
#include <stdio.h>
#include <cstring>
using namespace std;
int pangduan[11000]= {0};
int flag[11000]= {0};
int pangduan1[11000]= {0};
int flag1[11000]= {0};
int bf(int y,int z)
{
    if (y+z==10) return 1;
    if (y+z==0) return 9;
    else return y+z;
}
typedef struct password
{
    int a,b,c,d,m;
} password;
int L[32]= {1,0,0,0,-1,0,0,0,0,1,0,0,0,-1,0,0,0,0,1,0,0,0,-1,0,0,0,0,1,0,0,0,-1};
queue<password>Q;
queue<password>P;
int bfs(password,password);
int main()
{
    password W1,W2;
    int n,m;
    scanf("%d",&n);
    while(n--)
    {
        memset(pangduan,0,sizeof(pangduan));
        memset(pangduan1,0,sizeof(pangduan1));
        memset(flag1,0,sizeof(flag1));
        memset(flag,0,sizeof(flag));
        scanf("%d",&m);pangduan[m]=0;
        flag[m]=1;
        W1.d=m%10;
        m=m/10;
        W1.c=m%10;
        m=m/10;
        W1.b=m%10;
        W1.a=m/10;
        scanf("%d",&m);pangduan1[m]=0;
        flag1[m]=1;
        W2.d=m%10;
        m=m/10;
        W2.c=m%10;
        m=m/10;
        W2.b=m%10;
        W2.a=m/10;
        W1.m=W2.m=0;
        while(!Q.empty()) Q.pop();
        while(!P.empty()) P.pop();
        m=bfs(W1,W2);
        printf("%d\n",m);
    }
    return 0;
}
int bfs(password a,password b)
{
    Q.push(a);
    P.push(b);
    password c;
    int shu,bushu=999999;
    int k=0;
    while(1)
    {
        while(1)
        {
            c=Q.front();
            if(c.m!=k) break;
            Q.pop();
            shu=c.a*1000+c.b*100+c.c*10+c.d;
            if(flag1[shu]!=0)
            {
                if(c.m<bushu)
                    bushu=c.m+pangduan1[shu];
            }
            for(int i=0; i<8; i++)
            {
                a.a=bf(c.a,L[4*i]);
                a.b=bf(c.b,L[4*i+1]);
                a.c=bf(c.c,L[4*i+2]);
                a.d=bf(c.d,L[4*i+3]);
                a.m=c.m+1;
                shu=a.a*1000+a.b*100+a.c*10+a.d;
                if(flag[shu]) continue;
                else {pangduan[shu]=a.m;flag[shu]=1;}
                Q.push(a);
            }
            a.m=c.m+1;
            a.a=c.b;
            a.b=c.a;
            a.c=c.c;
            a.d=c.d;
            shu=a.a*1000+a.b*100+a.c*10+a.d;
            if(!pangduan[shu])
            {
                pangduan[shu]=a.m;
                flag[shu]=1;
                Q.push(a);
            }
            a.a=c.a;
            a.b=c.c;
            a.c=c.b;
            a.d=c.d;
            shu=a.a*1000+a.b*100+a.c*10+a.d;
            if(!pangduan[shu])
            {
                pangduan[shu]=a.m;
                flag[shu]=1;
                Q.push(a);
            }
            a.a=c.a;
            a.b=c.b;
            a.c=c.d;
            a.d=c.c;
            shu=a.a*1000+a.b*100+a.c*10+a.d;
            if(!pangduan[shu])
            {
                pangduan[shu]=a.m;
                flag[shu]=1;
                Q.push(a);
            }
        }
        if(bushu!=999999) return bushu;
        while(1)
        {
            c=P.front();
            if(c.m!=k) break;
            P.pop();
            shu=c.a*1000+c.b*100+c.c*10+c.d;
            if(flag[shu]!=0)
            {
                if(c.m<bushu)
                    bushu=c.m+pangduan[shu];
            }
            for(int i=0; i<8; i++)
            {
                a.a=bf(c.a,L[4*i]);
                a.b=bf(c.b,L[4*i+1]);
                a.c=bf(c.c,L[4*i+2]);
                a.d=bf(c.d,L[4*i+3]);
                a.m=c.m+1;
                shu=a.a*1000+a.b*100+a.c*10+a.d;
                if(flag1[shu]) continue;
                else {pangduan1[shu]=a.m;flag1[shu]=1;}
                P.push(a);
            }
            a.m=c.m+1;
            a.a=c.b;
            a.b=c.a;
            a.c=c.c;
            a.d=c.d;
            shu=a.a*1000+a.b*100+a.c*10+a.d;
            if(!pangduan1[shu])
            {
                pangduan1[shu]=a.m;
                flag1[shu]=1;
                P.push(a);
            }
            a.a=c.a;
            a.b=c.c;
            a.c=c.b;
            a.d=c.d;
            shu=a.a*1000+a.b*100+a.c*10+a.d;
            if(!pangduan1[shu])
            {
                pangduan1[shu]=a.m;
                flag1[shu]=1;
                P.push(a);
            }
            a.a=c.a;
            a.b=c.b;
            a.c=c.d;
            a.d=c.c;
            shu=a.a*1000+a.b*100+a.c*10+a.d;
            if(!pangduan1[shu])
            {
                pangduan1[shu]=a.m;
                flag1[shu]=1;
                P.push(a);
            }
        }
        if(bushu!=999999) return bushu;
        k++;
    }
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值