zoukankan      html  css  js  c++  java
  • leetcode752. 打开转盘锁

    我们可以将 0000 到 9999 这 10000 状态看成图上的 10000 个节点,两个节点之间存在一条边,当且仅当这两个节点对应的状态只有 1 位不同,且不同的那位相差 1(包括 0 和 9 也相差 1 的情况),并且这两个节点均不在数组 deadends 中。那么最终的答案即为 0000 到 target 的最短路径。

    我们用广度优先搜索来找到最短路径,从 0000 开始搜索。对于每一个状态,它可以扩展到最多 8 个状态,即将它的第 i = 0, 1, 2, 3 位增加 1 或减少 1,将这些状态中没有搜索过并且不在 deadends 中的状态全部加入到队列中,并继续进行搜索。注意 0000 本身有可能也在 deadends 中。

    破解密码的问题就像是一个树搜索的问题,把每一种一步变换的结果都放在该初状态的子节点里
    (用deadends和visited进行剪枝,deadends用于去掉包含死路的解法,visited用于避免已经走过的路)
    然后再去搜索这个target,搜索的深度就是最短的步数
    可以用BFS来实现

    class Solution {
    public:
        int openLock(vector<string>& deadends, string target) {
            int step=0;
            unordered_set<string> deadset(deadends.begin(),deadends.end());
            queue<string>tree;
            tree.push("0000");
            
            unordered_set<string> visited;
            visited.insert("0000");
            
            if(deadset.find("0000")!=deadset.end()) return -1;
            while(!tree.empty())
            {
                int n=tree.size();
                for(int i=0;i<n;i++)
                {
                    string cur=tree.front();
                    tree.pop();
                    if(cur==target)
                        return step;
                    //位上加一
                    for(int j=0;j<4;j++)
                    {
                        stringstream ss;
                        int cur_num;
                        string candidate1=cur;
                        ss<<candidate1[j];
                        ss>>cur_num;
                        cur_num=(cur_num+1)%10;
                        ss.clear();//清空输入输出流
                        ss<<cur_num;
                        ss>>candidate1[j];
                        ss.clear();
                        if(deadset.find(candidate1)==deadset.end() && visited.find(candidate1)==visited.end())
                        {
                            tree.push(candidate1);
                            visited.insert(candidate1);
                        }
                    }
                    //位上减一
                    for(int j=0;j<4;j++)
                    {
                        stringstream ss_1;
                        int cur_num_1;
                        string candidate2=cur;
                        ss_1<<candidate2[j];
                        ss_1>>cur_num_1;
                        cur_num_1-=1;
                        if(cur_num_1<0) 
                            cur_num_1+=10;
                        ss_1.clear();
                        ss_1<<cur_num_1;
                        ss_1>>candidate2;
                        ss_1.clear();
                        if(deadset.find(candidate2)==deadset.end() && visited.find(candidate2)==visited.end())
                        {
                            tree.push(candidate2);
                            visited.insert(candidate2);
                        }
                    }
                }
                step++;
            }
            return -1;  
        }
    };
  • 相关阅读:
    室内设计师招募中...
    winform控件部署于web中控件装载ie中
    Oracle10g在windows2003下双机热备安装
    购房风波(4)不了了之
    [原创]面向对象理解·抽象类和派生类理解和使用
    Infragistics NetAdvantage 2006 Volume 2 CLR 2.0曲折安装
    两个Javascript小tip
    PHP学习笔记之二
    C#开发语音机项目
    关于WebBrowser的DocumentText
  • 原文地址:https://www.cnblogs.com/renzmin/p/11914243.html
Copyright © 2011-2022 走看看