https://leetcode-cn.com/problems/open-the-lock/添加链接描述
思路:显然题目是另外一种类型的最短路问题,最优解可用
b
f
s
bfs
bfs解决。
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
unordered_map<string,bool> vis;
for(const string& s:deadends)
vis[s]=1;
int ans=-1;
using pr=pair<string,int>;
queue<pr> q;
if(vis.find("0000")!=vis.end())
return -1;
q.push(pr("0000",0));
vis["0000"]=1;
while(!q.empty())
{
pr f=q.front();
q.pop();
if(f.first==target)
{
ans=f.second;
break;
}
for(int i=0;i<4;i++)
{
for(int j=-1;j<=1;j+=2)
{
string tmp=f.first;
tmp[i]+=j;
if(tmp[i]>'9')
tmp[i]='0';
else if(tmp[i]<'0')
tmp[i]='9';
if(vis.find(tmp)==vis.end())
{
q.emplace(tmp,f.second+1);
vis[tmp]=1;
}
}
}
}
return ans;
}
};
思路二:通过A*求解。关键是如何计算预估函数,我们可以逐一统计从当前字符串到目标字符串的每一位的最小步数,然后把它们加起来即可。
class node{
public:
int total,cur,toend;
string s;
node(int c,string s,const string& target):cur(c),s(move(s))
{
toend=GetEstimate(target);
total=cur+toend;
}
bool operator <(const node &n)const
{
return total>n.total;
}
int GetEstimate(const string &target)
{
int ans=0;
for(int i=0;i<4;i++)
{
int tmp=abs(s[i]-target[i]);
ans+=min(tmp,10-tmp);
}
return ans;
}
};
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
if(target=="0000")
return 0;
unordered_map<string,bool> vis;
for(const string& s:deadends)
vis[s]=1;
int ans=-1;
priority_queue<node> q;
if(vis.find("0000")!=vis.end())
return -1;
q.emplace(0,"0000",target);
vis["0000"]=1;
while(!q.empty())
{
node f=q.top();
q.pop();
for(int i=0;i<4;i++)
{
for(int j=-1;j<=1;j+=2)
{
string tmp=f.s;
tmp[i]+=j;
if(tmp[i]>'9')
tmp[i]='0';
else if(tmp[i]<'0')
tmp[i]='9';
if(tmp==target)
return f.cur+1;
if(vis.find(tmp)==vis.end())
{
vis[tmp]=1;
q.emplace(f.cur+1,move(tmp),target);
}
}
}
}
return ans;
}
};