今天小编又来跟新了 没办法A题目速度不高啊 本人还在处于训练状态请多多包涵
最近在训练DFS以及BFS 今天我来说说神奇密码锁问题 在做这个题目的过程中有思路 然后想上网找找 发现没有博客写关于这个问题
所以我想讲讲我的解题思路
题目描述
小明忘记了旅行箱上的密码,现在他想自己暴力弄出密码来,但他又想知道最从一个数字到另一个数字最少需要多少步,现在请你帮忙。
另外,小明的密码箱很奇怪,只有四位数,上面的数字只有1到9,每次只能让每位数加1或者减1。按常识我们可以知道从1到9只需要减1,从9到1只需要加1。此外,你还能交换相邻的两个数字。如1234可以在一步后变成2134,但不能变成4231。
输入
第一行有一个整数:T,代表有多少组测试数据。
接下来T行,每行有两个整数(都是四位数),第一个是初状态,第二个是目标状态。
输出
每组数据输出一个整数,占一行。
样例输入
21234 21441111 9999
样例输出
24
首先在看这道题目时候我先没有考虑bfs以及dfs 我用一个3*3的二维数组来处理该位数字转换为其他位置上数字所需要的步数(包括互换),然后处理四次就可以了,我这样想过但是没有进行实现 感觉应该可以
好下面说一下DFS以及BFS的方法,我首先解释一下一个数变化有11种情况(每一位数字加减共8种 互换数字有三种 共11种)。我在分析的过程中把DFS排除了 因为在你往下走的过程中深度很大,你不知道跳出循环条件是什么 不过我今天听别人讲可以限制它的深度 如果在限制的深度中还是没有找到你要的答案 可以进一步加大深度直到你找到你的目标为止
至于BFS,其实思路是比较简单的 使用容器STL的队列 然后使用一个大小为10005的判断数组 如果走过为1 没有则为0 然后就是BFS的老套路了 先处理对头元素 取对头元素 (判断) 然后就是扩展 看是否走过 如果走过则跳过 如果没有则push 一直到找到目标为止
#include <iostream>
#include <algorithm>
#include <queue>
#include <stdio.h>
#include <cstring>
using namespace std;
int pangduan[11000]={0};
int bf(int y,int z)
{
if (y+z==10) return 1;
if (y+z==0) return 9;
else return y+z;
}
typedef struct password
{
int a,b,c,d,m;
}password;
int L[32]={1,0,0,0,-1,0,0,0,0,1,0,0,0,-1,0,0,0,0,1,0,0,0,-1,0,0,0,0,1,0,0,0,-1};
queue<password>Q;
int bfs(password,password);
int main()
{
password W1,W2;
int n,m;
scanf("%d",&n);
while(n--)
{
memset(pangduan,0,sizeof(pangduan));
scanf("%d",&m);
W1.d=m%10;m=m/10;W1.c=m%10;m=m/10;W1.b=m%10;W1.a=m/10;
scanf("%d",&m);
W2.d=m%10;m=m/10;W2.c=m%10;m=m/10;W2.b=m%10;W2.a=m/10;
W1.m=W2.m=0;
m=bfs(W1,W2);
printf("%d\n",m);
}
return 0;
}
int bfs(password a,password b)
{
Q.push(a);
password c;
int shu;
while(!Q.empty())
{
c=Q.front();Q.pop();
if(c.a==b.a&&c.b==b.b&&c.c==b.c&&c.d==b.d)
{
while(!Q.empty()) {Q.pop();}
return c.m;
}
for(int i=0;i<8;i++)
{
a.a=bf(c.a,L[4*i]);a.b=bf(c.b,L[4*i+1]);
a.c=bf(c.c,L[4*i+2]);a.d=bf(c.d,L[4*i+3]);
a.m=c.m+1;
shu=a.a*1000+a.b*100+a.c*10+a.d;
if(pangduan[shu]) continue;
else pangduan[shu]=1;
Q.push(a);
}
a.m=c.m+1;
a.a=c.b;a.b=c.a;a.c=c.c;a.d=c.d;shu=a.a*1000+a.b*100+a.c*10+a.d;if(!pangduan[shu]){pangduan[shu]=1;Q.push(a);}
a.a=c.a;a.b=c.c;a.c=c.b;a.d=c.d;shu=a.a*1000+a.b*100+a.c*10+a.d;if(!pangduan[shu]){pangduan[shu]=1;Q.push(a);}
a.a=c.a;a.b=c.b;a.c=c.d;a.d=c.c;shu=a.a*1000+a.b*100+a.c*10+a.d;if(!pangduan[shu]){pangduan[shu]=1;Q.push(a);}
}
}
写得挺简洁的 但是当我交的时候就错了 因为发现时间超时了 做题时候没有考虑这个问题 然后我只能使用双向BFS 由于第一次敲代
简洁度有待加强
#include <iostream>
#include <algorithm>
#include <queue>
#include <stdio.h>
#include <cstring>
using namespace std;
int pangduan[11000]= {0};
int flag[11000]= {0};
int pangduan1[11000]= {0};
int flag1[11000]= {0};
int bf(int y,int z)
{
if (y+z==10) return 1;
if (y+z==0) return 9;
else return y+z;
}
typedef struct password
{
int a,b,c,d,m;
} password;
int L[32]= {1,0,0,0,-1,0,0,0,0,1,0,0,0,-1,0,0,0,0,1,0,0,0,-1,0,0,0,0,1,0,0,0,-1};
queue<password>Q;
queue<password>P;
int bfs(password,password);
int main()
{
password W1,W2;
int n,m;
scanf("%d",&n);
while(n--)
{
memset(pangduan,0,sizeof(pangduan));
memset(pangduan1,0,sizeof(pangduan1));
memset(flag1,0,sizeof(flag1));
memset(flag,0,sizeof(flag));
scanf("%d",&m);pangduan[m]=0;
flag[m]=1;
W1.d=m%10;
m=m/10;
W1.c=m%10;
m=m/10;
W1.b=m%10;
W1.a=m/10;
scanf("%d",&m);pangduan1[m]=0;
flag1[m]=1;
W2.d=m%10;
m=m/10;
W2.c=m%10;
m=m/10;
W2.b=m%10;
W2.a=m/10;
W1.m=W2.m=0;
while(!Q.empty()) Q.pop();
while(!P.empty()) P.pop();
m=bfs(W1,W2);
printf("%d\n",m);
}
return 0;
}
int bfs(password a,password b)
{
Q.push(a);
P.push(b);
password c;
int shu,bushu=999999;
int k=0;
while(1)
{
while(1)
{
c=Q.front();
if(c.m!=k) break;
Q.pop();
shu=c.a*1000+c.b*100+c.c*10+c.d;
if(flag1[shu]!=0)
{
if(c.m<bushu)
bushu=c.m+pangduan1[shu];
}
for(int i=0; i<8; i++)
{
a.a=bf(c.a,L[4*i]);
a.b=bf(c.b,L[4*i+1]);
a.c=bf(c.c,L[4*i+2]);
a.d=bf(c.d,L[4*i+3]);
a.m=c.m+1;
shu=a.a*1000+a.b*100+a.c*10+a.d;
if(flag[shu]) continue;
else {pangduan[shu]=a.m;flag[shu]=1;}
Q.push(a);
}
a.m=c.m+1;
a.a=c.b;
a.b=c.a;
a.c=c.c;
a.d=c.d;
shu=a.a*1000+a.b*100+a.c*10+a.d;
if(!pangduan[shu])
{
pangduan[shu]=a.m;
flag[shu]=1;
Q.push(a);
}
a.a=c.a;
a.b=c.c;
a.c=c.b;
a.d=c.d;
shu=a.a*1000+a.b*100+a.c*10+a.d;
if(!pangduan[shu])
{
pangduan[shu]=a.m;
flag[shu]=1;
Q.push(a);
}
a.a=c.a;
a.b=c.b;
a.c=c.d;
a.d=c.c;
shu=a.a*1000+a.b*100+a.c*10+a.d;
if(!pangduan[shu])
{
pangduan[shu]=a.m;
flag[shu]=1;
Q.push(a);
}
}
if(bushu!=999999) return bushu;
while(1)
{
c=P.front();
if(c.m!=k) break;
P.pop();
shu=c.a*1000+c.b*100+c.c*10+c.d;
if(flag[shu]!=0)
{
if(c.m<bushu)
bushu=c.m+pangduan[shu];
}
for(int i=0; i<8; i++)
{
a.a=bf(c.a,L[4*i]);
a.b=bf(c.b,L[4*i+1]);
a.c=bf(c.c,L[4*i+2]);
a.d=bf(c.d,L[4*i+3]);
a.m=c.m+1;
shu=a.a*1000+a.b*100+a.c*10+a.d;
if(flag1[shu]) continue;
else {pangduan1[shu]=a.m;flag1[shu]=1;}
P.push(a);
}
a.m=c.m+1;
a.a=c.b;
a.b=c.a;
a.c=c.c;
a.d=c.d;
shu=a.a*1000+a.b*100+a.c*10+a.d;
if(!pangduan1[shu])
{
pangduan1[shu]=a.m;
flag1[shu]=1;
P.push(a);
}
a.a=c.a;
a.b=c.c;
a.c=c.b;
a.d=c.d;
shu=a.a*1000+a.b*100+a.c*10+a.d;
if(!pangduan1[shu])
{
pangduan1[shu]=a.m;
flag1[shu]=1;
P.push(a);
}
a.a=c.a;
a.b=c.b;
a.c=c.d;
a.d=c.c;
shu=a.a*1000+a.b*100+a.c*10+a.d;
if(!pangduan1[shu])
{
pangduan1[shu]=a.m;
flag1[shu]=1;
P.push(a);
}
}
if(bushu!=999999) return bushu;
k++;
}
}