Open the lock

双向广搜
#include<stdio.h>
#include<string.h>
#include<string>
#include<queue>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;

struct node
{
int a[4]; //密码四位数字
int step; //执行步数
}s,e; //初始密码、开锁密码
int vis[10001]; //标记当前状态是否有走过(从前往后走为1,从后往前走为2,没有走过为0)
int mp[10001]; //标记走到当前状态的步数
int get_num(int c[]) //数组转化成整数
{
int n=0;
for(int i=0;i<4;i++)
{
n*=10;
n+=c[i];
}
return n;
}
int bfs()
{
memset(vis,0,sizeof(vis)); //初始化数组
memset(mp,0,sizeof(mp));
queue<node>p,q; //初始化队列
int tmp; //当前位置
tmp=get_num(s.a);
vis[tmp]=1; //起始搜索记号
tmp=get_num(e.a);
vis[tmp]=2; //结束搜索记号

node u,v;
p.push(s); //开始节点
q.push(e); //结束节点
while(!q.empty()||!p.empty())
{
if(!p.empty()) //从前向后搜索
{
u=p.front();
p.pop();
for(int i=0;i<4;i++) //四位密码
{
v=u; //u更新成v
v.a[i]=u.a[i]+1;////+1
if(v.a[i]==10) //换密码不牵扯进位
v.a[i]=1;
tmp=get_num(v.a); //第一次
if(vis[tmp]==0) //从前往后没有走过
{
v.step=u.step+1;
mp[tmp]=v.step; //标记走到当前状态的步数
vis[tmp]=1;
p.push(v);
}
else if(vis[tmp]==2) //从前往后与从后往前有交叉
return u.step+mp[tmp]+1; //返回交汇点的步骤:前+后
v.a[i]=u.a[i]-1;//-1
if(v.a[i]==0)
v.a[i]=9;
tmp=get_num(v.a); //第二次
if(vis[tmp]==0)
{
v.step=u.step+1;
mp[tmp]=v.step;
vis[tmp]=1;
p.push(v);
}
else if(vis[tmp]==2)
return u.step+mp[tmp]+1;//
}
for(int i=0;i<3;i++) //交换
{
v=u;
int k=v.a[i];
v.a[i]=v.a[i+1];
v.a[i+1]=k;
tmp=get_num(v.a); //第三次
if(vis[tmp]==0)
{
v.step=u.step+1;
mp[tmp]=v.step;
vis[tmp]=1;
p.push(v);
}
else if(vis[tmp]==2)
return u.step+mp[tmp]+1;
}

}
if(!q.empty()) //从后向前搜索
{
u=q.front();
q.pop();
for(int i=0;i<4;i++)
{
v=u;
v.a[i]=u.a[i]+1;
if(v.a[i]==10)
v.a[i]=1;
tmp=get_num(v.a);
if(vis[tmp]==0)
{
v.step=u.step+1;
mp[tmp]=v.step;
vis[tmp]=2;
q.push(v);
}
else if(vis[tmp]==1) //从后往前与从前往后哟交叉
return u.step+mp[tmp]+1;

v.a[i]=u.a[i]-1;
if(v.a[i]==0)
v.a[i]=9;
tmp=get_num(v.a);
if(vis[tmp]==0)
{
v.step=u.step+1;
mp[tmp]=v.step;
vis[tmp]=2;
q.push(v);
}
else if(vis[tmp]==1)
return u.step+mp[tmp]+1;
}
for(int i=0;i<3;i++)
{
v=u;
int k=v.a[i];
v.a[i]=v.a[i+1];
v.a[i+1]=k;
tmp=get_num(v.a);
if(vis[tmp]==0)
{
v.step=u.step+1;
mp[tmp]=v.step;
vis[tmp]=2;
q.push(v);
}
else if(vis[tmp]==1)
return u.step+mp[tmp]+1;
}
}
}
}
int main()
{
int t;
scanf("%d",&t); //测试次数
while(t--)
{
char s1[10],s2[10];
scanf("%s%s",s1,s2); //
for(int i=0;i<4;i++)
s.a[i]=s1[i]-'0';
for(int i=0;i<4;i++)
e.a[i]=s2[i]-'0';
s.step=0;
e.step=0;
printf("%d\n",bfs());
}
return 0;
}

笔记:双向广搜是用BFS从开始与结束一起搜索,直到执行到交汇上,就停止搜索,输出结果,如果队列空也没有元素,即无解

版权声明:

本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/u012861385/article/details/32731433

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注