HDU——1195Open the Lock(双向BFS)
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
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.
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.
1234
2144
1111
9999
4
最近懂了点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)的更多相关文章
- HDU 3085 Nightmare II 双向bfs 难度:2
http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...
- HDU 1043 Eight(双向BFS+康托展开)
http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...
- HDU 3085 Nightmare Ⅱ(双向BFS)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 题目大意:给你一张n*m地图上,上面有有 ‘. ’:路 ‘X':墙 ’Z':鬼,每秒移动2步,可 ...
- HDU 6171 Admiral(双向BFS+队列)题解
思路: 最大步骤有20,直接BFS会超时. 因为知道开始情况和结果所以可以用双向BFS,每个BFS规定最大步骤为10,这样相加肯定小于20.这里要保存每个状态搜索到的最小步骤,用Hash储存.当发现现 ...
- hdu 1043 Eight(双向bfs)
题意:经典八数码问题 思路:双向bfs ps:还有a*算法(还不会)等解法. 代码: #include<iostream> #include<stdio.h> #include ...
- 2017多校第10场 HDU 6171 Admiral 双向BFS或者A*搜索
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6171 题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以 ...
- ACM-BFS之Open the Lock——hdu1195(双向BFS)
这道题的0基础版本号,暴力BFS及题目详情请戳:http://blog.csdn.net/lttree/article/details/24658031 上回书说道,要用双向BFS来尝试一下. 最终A ...
- HDU 1242 -Rescue (双向BFS)&&( BFS+优先队列)
题目链接:Rescue 进度落下的太多了,哎╮(╯▽╰)╭,渣渣我总是埋怨进度比别人慢...为什么不试着改变一下捏.... 開始以为是水题,想敲一下练手的,后来发现并非一个简单的搜索题,BFS做肯定出 ...
- 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 ...
随机推荐
- SQL2005中使用backup、restore来备份和恢复数据库
在SQL2005数据库中利用SQL语句进行数据备份与还原: 备份backup:backup database 数据库名称 tO disk = 备份路径例:BACKUP DATABASE test TO ...
- JavaScript面试系列:JavaScript设计模式之桥接模式和懒加载
我写的程序员面试系列文章 Java面试系列-webapp文件夹和WebContent文件夹的区别? 程序员面试系列:Spring MVC能响应HTTP请求的原因? Java程序员面试系列-什么是Jav ...
- OpenGL列主元矩阵和列主序存储
OpenGL矩阵要考虑两个点,一个是向量如何排布,一个是矩阵如何存储和恢复. 1.排布 排布决定了运算的顺序.OpenGL使用的是列主元,它的意思就是一个4X4的矩阵是由4个列向量构成(这里的v1,v ...
- Gersgorin 圆盘
将学习到什么 好多. Gersgorin 圆盘定理 对任何 \(A \in M_n\),我们总可以记 \(A=D+B\),其中 \(D=\mathrm{diag}(a_{11},\cdots, ...
- gson对象的相互转换
参见 http://www.javacreed.com/gson-deserialiser-example/
- XDB基于Library的备份及恢复
基于standalone全备份 语句: xdb backup --federation xhive://localhost:1235 --standalone --file E:\xdbData\xD ...
- visibilitychange 标签可见性
var pageVisibility = document.visibilityState;// 监听 visibility change 事件document.addEventListener('v ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
- 【php】Windows PHP及xdebug安装 安装
php version 7.0 redis 下载地址 https://pecl.php.net/package/redis 7.0版本的redis不再依赖php_igbinary.dll扩展,可以独立 ...
- 快照、克隆,xshell优化,Linux历史
目录 一.虚拟拍照功能 二.虚拟机克隆功能 三.Xshell的优化 四.介绍Linux历史 一.虚拟拍照功能 1.拍摄快照 关机状态拍照 关机命令:shutdown -h now 或者 init 0 ...