• 【bfs】密码锁-C++


    Description
    现在一个紧急的任务是打开一个密码锁。密码由四位数字组成,每个数字从 1 到 9 进行编号。每次可以对任何数字加 1 或减 1。当将9加 1 时,数字将变为1,当1减 1 的时,数字将变为9。您也可以与邻居交换数字,每一个行动记做一步。现在你的任务是使用最小的步骤来打开锁。
    注意:最左边的数字不是最右边数字的邻居。
    Input	
    第一行输入四位数字,表示密码锁的初始状态。第二行输入四位数字,表示开锁的密码。
    Output
    输出一个整数,表示最小步骤。
    Sample Input 1 
    1234
    2144
    Sample Output 1
    2
    
    

    这道题一看,似乎不该用搜索。
    又一想,这种题目也只能使用bfs来完成。

    但是怎么打标记?

    普通的一维的vis数组已经无法满足这道题目的需求了,应该怎么解决?
    再认真一看,它的起始和重点都是4个数字构成,我们可以把由4个数字组成的一组密码记为一种状态,即:
    当密码为abcd时,对应的标记就应该记为vis[a][b][c][d]=1;
    简单来说,就是通过四维数组,完成打标记这一步。
    接下来的操作就是最基本的bfs,代码随便敲下来就可以了。
    按照题意,每个密码能够进行的拓展操作分别为:
    每一位加/减一位构成的新密码;
    分别交换第1,2/2,3/3,4位构成的新密码;
    然后判断,如果是没有打标记的,打进队列然后打标记即可。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    struct node
    {
        int aa[4];
        int t;
        node(){};
        node(int a0,int a1,int a2,int a3,int t_)
        {
            aa[0]=a0;
            aa[1]=a1;
            aa[2]=a2;
            aa[3]=a3;
            t=t_;
        }
    }mb;//mb:目标 
    bool x[10][10][10][10];
    queue<node> qu;
    
    
    bool in(node a)
    {
        if(a.aa[0]==mb.aa[0]&&a.aa[1]==mb.aa[1]&&a.aa[2]==mb.aa[2]&&a.aa[3]==mb.aa[3])return false;
        else return true;
    }
    
    int bfs(int a,int b,int c,int d)
    {
        qu.push(node(a,b,c,d,0));
        x[a][b][c][d]=1;
        while(in(qu.front())&&!qu.empty())
        {
            node now=qu.front();
            qu.pop();
            
            
            if(!x[now.aa[1]][now.aa[0]][now.aa[2]][now.aa[3]])
            {
                qu.push(node(now.aa[1],now.aa[0],now.aa[2],now.aa[3],now.t+1));
                x[now.aa[1]][now.aa[0]][now.aa[2]][now.aa[3]]=1;
            }
            //a,b,c,d->b,a,c,d 
            
            if(!x[now.aa[0]][now.aa[2]][now.aa[1]][now.aa[3]])
            {
                qu.push(node(now.aa[0],now.aa[2],now.aa[1],now.aa[3],now.t+1));
                x[now.aa[0]][now.aa[2]][now.aa[1]][now.aa[3]]=1;
            }
            //a,b,c,d->a,c,b,d
            
            if(!x[now.aa[0]][now.aa[1]][now.aa[3]][now.aa[2]])
            {
                qu.push(node(now.aa[0],now.aa[1],now.aa[3],now.aa[2],now.t+1));
                x[now.aa[0]][now.aa[1]][now.aa[3]][now.aa[2]]=1;
            }
            //a,b,c,d->a,b,d,c
            //因为a和d 不能直接交换所以就只有这三种情况 
            for(int i=0;i<4;i++)
            {
                node nxt=now;
                
                nxt.aa[i]++;
                nxt.t++;
                
                if(nxt.aa[i]==10)nxt.aa[i]=1;
                
                if(!x[nxt.aa[0]][nxt.aa[1]][nxt.aa[2]][nxt.aa[3]])
                {
                    qu.push(nxt);
                    x[nxt.aa[0]][nxt.aa[1]][nxt.aa[2]][nxt.aa[3]]=1;
                }
                
            }
            
            for(int i=0;i<4;i++)
            {
                node nxt=now;
                
                nxt.aa[i]--;
                nxt.t++;
                
                if(nxt.aa[i]==0)nxt.aa[i]=9;
                
                if(!x[nxt.aa[0]][nxt.aa[1]][nxt.aa[2]][nxt.aa[3]])
                {
                    qu.push(nxt);
                    x[nxt.aa[0]][nxt.aa[1]][nxt.aa[2]][nxt.aa[3]]=1;
                }
                
            }
        }
        
        return qu.front().t;
        
    }
    
    int main()
    {
        int st,ed;
        cin>>st>>ed;
        
        mb=node(ed/1000,ed%1000/100,ed%100/10,ed%10,0);
        
        cout<<bfs(st/1000,st%1000/100,st%100/10,st%10)<<endl;
        return 0;
    }
    

    ov.

    个人博客地址: www.moyujiang.com 或 moyujiang.top
  • 相关阅读:
    为什么我要学习qt quick
    geometory Intersect
    删除kubernetes节点的正确姿势
    乞丐版docker私有仓库搭建
    kubernetes集群中由于某些原因导致etcd节点没有删干净,需要手动清理etcd节点
    k8s coredns设置上游name server
    虚拟机架设koolshare软路由
    文件类型特征码
    深入字节码 -- 计算方法执行时间
    启迪思维:二叉树
  • 原文地址:https://www.cnblogs.com/moyujiang/p/11167781.html
Copyright © 2020-2023  润新知