Open the Lock

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6016    Accepted Submission(s): 2680

Problem Description
Now an emergent task for you is to open a password lock. The password is consisted of four digits. Each digit is numbered from 1 to 9. 
Each time, you can add or minus 1 to any digit. When add 1 to '9', the digit will change to be '1' and when minus 1 to '1', the digit will change to be '9'. You can also exchange the digit with its neighbor. Each action will take one step.

Now your task is to use minimal steps to open the lock.

Note: The leftmost digit is not the neighbor of the rightmost digit.

 
Input
The input file begins with an integer T, indicating the number of test cases.

Each test case begins with a four digit N, indicating the initial state of the password lock. Then followed a line with anotther four dight M, indicating the password which can open the lock. There is one blank line after each test case.

 
Output
For each test case, print the minimal steps in one line.
 
Sample Input
2
1234
2144

1111
9999

 
Sample Output
2
4
 
Author
YE, Kai

最近懂了点BFS套路,这题用普通BFS本来就是大水题一道,但是可以用双向BFS写,据说若干若原来复杂度为K^n,则双向会大约是2*K^(n/2)。在POJ上的题目比较明显,从400+MS降到16MS。但是这题两者都是62MS(我搞了半天这结果一样……)代码WA很久,不解一个下午,也改了很久,看了很多其他人写的这题的题解,代码量比较大而且我使用字符数组他们是转换为int。方式不同也看起来比较复杂不太能懂。但是想起来中途看到一篇讲双向BFS的文章双向BFS,然后发现自己跟作者讲的情况很符合,似乎是搜索的时候跳出太快了,没有搜完就结束了。也就是所谓的每一层都要搜遍。然后按照作者所说加了个队列数量判断来保持两个搜索队列大小相对平衡,然后就开心地过了。

双搜WA的可以看下这组数据(类似于答案应该是前两位交换,后两位加减):

5
1919
9128

原来代码答案是4,但其实是3(1、9交换,后面加减)。

代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
const double PI=acos(-1.0);
const int N=100010;
struct info
{
char s[5];
int step;
};
info goal,ori;
int pos[N];
int vis[N];
inline int change(char s[])
{
int r=0;
for (int i=0; i<4; ++i)
r=r*10+s[i]-'0';
return r;
}
int T_bfs()
{
queue<info>Qf;
queue<info>Qb;
Qf.push(ori);
Qb.push(goal);
while ((!Qf.empty())||(!Qb.empty()))
{
if(!Qf.empty()&&(Qf.size()>Qb.size()))//这里加了个数量判断就AC了
{
info now1=Qf.front();
Qf.pop();
for (int i=0; i<4; i++)
{
info v=now1;
v.s[i]--;
if(v.s[i]<49)
v.s[i]='9';
int num=change(v.s);
if(!pos[num])
{
v.step=now1.step+1;
pos[num]=1;
vis[num]=v.step;
Qf.push(v);
}
else if(pos[num]==2)
return vis[num]+vis[change(now1.s)];
}
for (int i=0; i<4; i++)
{
info v=now1;
v.s[i]++;
if(v.s[i]>57)
v.s[i]='1';
int num=change(v.s);
if(!pos[num])
{
v.step=now1.step+1;
pos[num]=1;
vis[num]=v.step;
Qf.push(v);
}
else if(pos[num]==2)
return vis[num]+vis[change(now1.s)];
}
for (int i=0; i<3; i++)
{
info v=now1;
swap(v.s[i],v.s[i+1]);
int num=change(v.s);
if(!pos[num])
{
pos[num]=1;
v.step=now1.step+1;
vis[num]=v.step;
Qf.push(v);
}
else if(pos[num]==2)
return vis[num]+vis[change(now1.s)];
}
} if(!Qb.empty())
{
info now2=Qb.front();
Qb.pop();
for (int i=0; i<4; i++)
{
info v=now2;
v.s[i]--;
if(v.s[i]<49)
v.s[i]='9';
int num=change(v.s);
if(!pos[num])
{
v.step=now2.step+1;
pos[num]=2;
vis[num]=v.step;
Qb.push(v);
}
else if(pos[num]==1)
return vis[num]+vis[change(now2.s)];
}
for (int i=0; i<4; i++)
{
info v=now2;
v.s[i]++;
if(v.s[i]>57)
v.s[i]='1';
int num=change(v.s);
if(!pos[num])
{
v.step=now2.step+1;
pos[num]=2;
vis[num]=v.step;
Qb.push(v);
}
else if(pos[num]==1)
return vis[num]+vis[change(now2.s)];
}
for (int i=0; i<3; i++)
{
info v=now2;
swap(v.s[i],v.s[i+1]);
int num=change(v.s);
if(!pos[num])
{
v.step=now2.step+1;
pos[num]=2;
vis[num]=v.step;
Qb.push(v);
}
else if(pos[num]==1)
return vis[num]+vis[change(now2.s)];
}
}
}
}
int main(void)
{
int tcase;
scanf("%d",&tcase);
while (tcase--)
{
MM(pos);
MM(vis);
scanf("%s %s",ori.s,goal.s);
ori.step=0;
goal.step=0;
pos[change(ori.s)]=1;
pos[change(goal.s)]=2;
vis[change(ori.s)]=0;
vis[change(goal.s)]=0;
!strcmp(ori.s,goal.s)?puts("0"):printf("%d\n",T_bfs()+1);
}
return 0;
}

HDU——1195Open the Lock(双向BFS)的更多相关文章

  1. HDU 3085 Nightmare II 双向bfs 难度:2

    http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...

  2. HDU 1043 Eight(双向BFS+康托展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

  3. HDU 3085 Nightmare Ⅱ(双向BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 题目大意:给你一张n*m地图上,上面有有 ‘. ’:路 ‘X':墙 ’Z':鬼,每秒移动2步,可 ...

  4. HDU 6171 Admiral(双向BFS+队列)题解

    思路: 最大步骤有20,直接BFS会超时. 因为知道开始情况和结果所以可以用双向BFS,每个BFS规定最大步骤为10,这样相加肯定小于20.这里要保存每个状态搜索到的最小步骤,用Hash储存.当发现现 ...

  5. hdu 1043 Eight(双向bfs)

    题意:经典八数码问题 思路:双向bfs ps:还有a*算法(还不会)等解法. 代码: #include<iostream> #include<stdio.h> #include ...

  6. 2017多校第10场 HDU 6171 Admiral 双向BFS或者A*搜索

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6171 题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以 ...

  7. ACM-BFS之Open the Lock——hdu1195(双向BFS)

    这道题的0基础版本号,暴力BFS及题目详情请戳:http://blog.csdn.net/lttree/article/details/24658031 上回书说道,要用双向BFS来尝试一下. 最终A ...

  8. HDU 1242 -Rescue (双向BFS)&amp;&amp;( BFS+优先队列)

    题目链接:Rescue 进度落下的太多了,哎╮(╯▽╰)╭,渣渣我总是埋怨进度比别人慢...为什么不试着改变一下捏.... 開始以为是水题,想敲一下练手的,后来发现并非一个简单的搜索题,BFS做肯定出 ...

  9. HDU 2612 Find a way(双向bfs)

    题目代号:HDU 2612 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2612 Find a way Time Limit: 3000/1000 M ...

随机推荐

  1. DVWA之命令注入(command injection)

    Command injection就是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的 LOW 无论是Windows还是Linux,都可以使用&&连接多个命令 执行 ...

  2. Spring MVC系列[2]——参数传递及重定向

    1.目录结构 2.代码 <?xml version="1.0" encoding="UTF-8"?> <web-app version=&qu ...

  3. SVN几个重要的问题

    本文不是系统地讲解SVN,只是对SVN中一些重要的或者笔者一直混淆的问题做简要归纳. SVN的安装可以参考笔者的另一篇技术随笔<SVN安装使用小结>. 1.既然能够通过SVN得到“每一个版 ...

  4. 洛谷 P2916 [USACO08NOV]为母牛欢呼Cheering up the Cows

    题目描述 Farmer John has grown so lazy that he no longer wants to continue maintaining the cow paths tha ...

  5. 洛谷 2299 Mzc和体委的争夺战

    题目背景 mzc与djn第四弹. 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁(做过前三弹的都知道).但如此之多的男家丁吸引来了我们的体委(矮胖小伙),他要来与mzc争夺男家丁. mzc很生气 ...

  6. 2012-2013 ACM-ICPC, NEERC, Central Subregional Contest C Sequence (打表)

    打个表找找规律,到24445的时候乘2以后产生了0出现循环. 一般地,判断循环节是否存在可以用Floyd判圈算法. #include<bits/stdc++.h> using namesp ...

  7. Thread源码分析-java8

    1.Thread特性分析 守护线程Daemon 定性:支持性线程,主要用于程序中后台调度以及支持性工作. 当JVM中不存在Daemon线程时,JVM将会退出. 将一个线程设定为Daemon的方法: 调 ...

  8. Asp.Net Core 入门(九)—— 环境变量 TagHelper

    我们在之前讲Program.cs文件做了什么的时候,提到启动CreaeDefaultBuilder会获取环境变量来做一些判断之类的操作.那么我们的Taghelper也可以使用“ASPNETCORE_E ...

  9. VM虚拟机下的Linux不能上网

    虚拟机linux上网配置 图解教程 首先查看window7主机下的网络配置VMNet1或VMNet8是否开启,其实linux系统的网络连接跟linux系统一致 在虚拟机界面将桥接改为NAT连接 点虚拟 ...

  10. java面试基础篇(二)

    上一篇,我们说了一下线程和Map,或许那些太抽象,不太好理解,也不太方便记忆,我们这次说一些简单的. 1.Q:java的基本数据类型有哪些? A:四种整数类型(byte.short.int.long) ...