问题 D: 神奇密码锁
来源:互联网 发布:域名被墙做跳转有用吗 编辑:程序博客网 时间:2024/05/20 13:13
今天小编又来跟新了 没办法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++; }}
阅读全文
1 0
- 问题 D: 神奇密码锁
- 搜索 问题 D: 神奇密码锁
- 神奇密码锁
- 神奇密码锁
- 神奇密码锁 bfs
- 神奇密码锁(BFS)
- 密码锁问题
- 神奇密码锁 BFS (枚举) 进位转换 memcmp
- 密码锁
- 密码锁
- openjudge 特殊密码锁(开关问题)
- 043day(特殊密码锁问题的思考)
- 神奇的6174问题
- 神奇3D圣诞树实现源码!
- Problem D: qwb与神奇的序列
- 电子密码锁
- 电子密码锁
- 简单密码锁
- Linux命令分析: cp
- 工程通过git方式导入idea
- Travelling HDU
- FEC相关知识
- springMVC 获取.properties中属性值
- 问题 D: 神奇密码锁
- [OpenJudge2404]Ride to Office
- 大战飞碟flash游戏 帧动画
- shell脚本 日志文件批量导入hive
- Android屏幕适配dp、px两套解决办法
- 梯度下降优化算法总结
- 线段树 Circular RMQ
- 扫码售后系统开发公司
- synchronize用法