bfs打开转盘锁

题目描述
转盘锁有四位,每位10个数字,每次只能转一位,而且转的过程中不能出现deadends中的情况,求出最后转几步才能的出target。
一串字符串往上往下拨一位会有8种情况,相当于一个节点有8个邻接节点,在这么一个图中,只有一个终点,而且有的节点是不能用的,题目最后转换成BFS求最短路径。
而DFS求最短路径需要遍历整张图之后,保存所有的结果在选出最优的,在时间上已经败了。
求最短路径的时候,要避免走重复的路,所以要记录已经走过的路,基于这一点,可以把那些deadends条件的节点当成已经走过的路,省的另开空间去判断。

//608 ms, 33.9 MB
class Solution {
public:
	//向上拨一位,string可以直接通过下标访问已有元素
    string getUp(string source, int UpBit){
        string res = source;
        if(res[UpBit]=='9')
            res[UpBit] = '0';
        else
            res[UpBit]+=1;
        return res;
    }
    //向下拨一位
    string getDown(string source, int DownBit){
        string res = source;
        if(res[DownBit]=='0')
            res[DownBit] = '9';
        else
            res[DownBit]-=1;
        return res;
    }
    int openLock(vector<string>& deadends, string target) {
        queue<string> q;
        unordered_set<string> visited;
        int step = 0;
        //将dead情况视为visited
        for(int i = 0;i < deadends.size(); i ++){
            visited.insert(deadends[i]);
        }
        //一种极端的情况是,起始状态就是dead
        if(visited.count("0000"))
            return -1;
        q.push("0000");
        visited.insert("0000");
        while(!q.empty()){
            int sz = q.size();
            for(int i=0;i<sz;i++){
                string tmp = q.front();
                q.pop();
                if(tmp==target){
                    return step;
                }
                //一个节点有八个邻接节点
                for(int j=0;j<4;j++){
                    string tmpUp = getUp(tmp, j);
                    if(!visited.count(tmpUp)){
                        q.push(tmpUp);
                        visited.insert(tmpUp);
                    }
                    string tmpDown = getDown(tmp, j);
                    if(!visited.count(tmpDown)){
                        q.push(tmpDown);
                        visited.insert(tmpDown);
                    }
                }
            }
            step++;
        }
        return -1;
    }
};
unordered_set中判断是否存在某个元素,可以用count()函数,
若不存在函数返回0,存在返回1
#include<cstdio>
#include<iostream>
#include<unordered_set> 
using namespace std;
main(){
    unordered_set<int> us;
    us.insert(1);
    us.insert(2);
    us.insert(3);
    cout<<us.count(6)<<endl;
    return 0;
}
这一部分是把string转换成char*char[] 来处理的前置
c语言中没有string类型,可以通过string类对象的成员函数c_str()把string对象转换成c中的字符串样式。
const char *c_str();
c_str()函数返回一个指向正规C字符串的指针常量, 内容与本string串相同. 
注意:一定要使用strcpy()函数 等来操作c_str()返回的指针 
不要这样: 
char* c; 
string s="1234"; 
//c最后指向的内容是垃圾,因为s对象被析构,其内容被处理
//同时,编译器也将报错——将一个const char 赋与一个char  
c = s.c_str();

应该这样:
char c[20]; 
string s="1234"; 
strcpy(c,s.c_str()); 
这样才不会出错,c_str()返回的是一个const指针,不能对其进行操作

再举个例子
c_str()char* 形式传回 string 内含字符串
如果一个函数要求char*参数,可以使用c_str()方法: 
string s = "Hello World!";
printf("%s", s.c_str()); //输出 "Hello World!"

传统的BFS框架都是从起点开始往四周扩散,遇到终点停止。而双向BFS优化的思路是,起点和终点同时向四周扩散,当两个方向有交集的时候停止。
这个思路的前提是知道终点。起点、终点同时保留一个扩散的集合,当两个集合有交集终止。
区别在于传统的要走一棵树,双向走半棵树就会得到,但是从O(N)和O(N/2)的角度看时间复杂度是一样的。按下不表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值