ACM-BFS之Open the Lock——hdu1195(双向BFS)
这道题的0基础版本号,暴力BFS及题目详情请戳:http://blog.csdn.net/lttree/article/details/24658031
上回书说道,要用双向BFS来尝试一下。
最终AC了,
双向BFS,就是从两个点寻找一个共同的中间点。
然后把各自到这个中间点的步数加起来,及为最短步数。
肯定有人问了。双向BFS有啥优点捏?
鄙人,有图有真相!
单BFS:
双向BFS:
发现了不?
尤其是随着搜索广度的增大。那个范围是相当di啊!
双向BFS做法事实上不难,两个队列。
一个从头開始搜。一个从尾開始搜。
可是要注意一点,要逐层搜索。不要逐点搜索呀~
要在 正向的同一层搜索完后,再去搜索反向的对应层!
什么叫逐层搜索呢?
对于这道题而言,VIS数组须要记录到达该点的步数,
对于每层搜索要把,同一步数的点全出队列遍历一遍,再进行反向搜索。
OK。这是对于这道题的双向广搜代码(感觉就是把两个广搜叠起来就OK了)
/**************************************
***************************************
* Author:Tree *
*From :http://blog.csdn.net/lttree *
* Title : Scrambled Polygon *
*Source: hdu 1195 *
* Hint : 双向BFS *
***************************************
**************************************/ #include <iostream>
#include <string.h>
#include <queue>
using namespace std;
struct VIS
{
int flag,step;
}vis[10001];
struct Key
{
int k[4],step;
friend bool operator <(Key a,Key b)
{
return a.step<b.step;
}
};
int ini[4],ans[4],dis[2]={-1,1};
int solu[9]={9,1,2,3,4,5,6,7,8};
bool judge(Key a)
{
for(int i=0;i<4;++i)
if( a.k[i]!=ans[i] )
return false;
return true;
}
// 用来做VIS数组
int total(Key a)
{
int i,sum;
sum=0;
for(i=0;i<4;++i)
sum=sum*10+a.k[i];
return sum;
}
int bfs(void)
{
memset(vis,0,sizeof(vis));
queue <Key> q;
queue <Key> p;
Key pre,lst;
int i,t,sum,sp=0; // 初始化。。。 for(i=0;i<4;++i)
pre.k[i]=ini[i];
sum=total(pre);
vis[sum].flag=1;
vis[sum].step=0;
pre.step=0;
q.push(pre); for(i=0;i<4;++i)
lst.k[i]=ans[i];
sum=total(lst);
vis[sum].flag=2;
vis[sum].step=0;
lst.step=0;
p.push(lst); while( !q.empty() && !p.empty() )
{
// 为了遍历每一层的情况,所以用sp来控制层数
// 正向搜索
while( q.front().step==sp )
{
pre=q.front();
q.pop();
for(i=0; i<4; ++i)
{
if( pre.k[i]!=ans[i] )
{
for(t=0; t<2; ++t)
{
lst=pre;
lst.k[i]=solu[(pre.k[i]+dis[t])%9];
sum=total(lst);
lst.step=pre.step+1;
if( vis[sum].flag==1 ) continue;
if( vis[sum].flag==2 ) return lst.step+vis[sum].step;
vis[sum].flag=1;
vis[sum].step=lst.step;
q.push(lst);
}
}
}
for(i=0; i<3; ++i)
{
lst=pre;
lst.k[i]=pre.k[i+1];
lst.k[i+1]=pre.k[i];
sum=total(lst);
lst.step=pre.step+1;
if( vis[sum].flag==1 ) continue;
if( vis[sum].flag==2 ) return lst.step+vis[sum].step;
vis[sum].flag=1;
vis[sum].step=lst.step;
q.push(lst);
}
}
// 反向搜索
while( p.front().step==sp )
{
pre=p.front();
p.pop(); for(i=0; i<4; ++i)
{
if( pre.k[i]!=ini[i] )
{
for(t=0; t<2; ++t)
{
lst=pre;
lst.k[i]=solu[(pre.k[i]+dis[t])%9];
sum=total(lst);
lst.step=pre.step+1;
if( vis[sum].flag==2 ) continue;
if( vis[sum].flag==1 ) return lst.step+vis[sum].step;
vis[sum].flag=2;
vis[sum].step=lst.step;
p.push(lst);
}
}
} for(i=0; i<3; ++i)
{
lst=pre;
lst.k[i]=pre.k[i+1];
lst.k[i+1]=pre.k[i];
sum=total(lst);
lst.step=pre.step+1;
if( vis[sum].flag==2 ) continue;
if( vis[sum].flag==1 ) return lst.step+vis[sum].step; vis[sum].flag=2;
vis[sum].step=lst.step;
p.push(lst);
}
}
++sp;
}
}
int main()
{
int i,s,test;
char c;
cin>>test;
while( test-- )
{
// 输入数据
for(i=0;i<4;++i)
{
cin>>c;
ini[i]=c-'0';
}
for(i=0;i<4;++i)
{
cin>>c;
ans[i]=c-'0';
} s=bfs();
cout<<s<<endl;
}
return 0;
}
ACM-BFS之Open the Lock——hdu1195(双向BFS)的更多相关文章
- HDU1195 双向BFS(或BFS)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1195 , 双向BFS或者直接BFS也可以过. 其实这道题只是单向BFS就可以过的,但是为了练算法,所以 ...
- HDU——1195Open the Lock(双向BFS)
Open the Lock Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- HDU 3085 Nightmare II 双向bfs 难度:2
http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...
- 2017多校第10场 HDU 6171 Admiral 双向BFS或者A*搜索
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6171 题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以 ...
- 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步,可 ...
- HDU3085 Nightmare Ⅱ —— 双向BFS + 曼哈顿距离
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Other ...
- HDU1401(双向BFS)
题意:http://acm.hdu.edu.cn/showproblem.php?pid=1401 给你8*8的棋盘和4个棋子初始位置.最终位置,问你能否在8次操作后达到该状态. 思路: 双向BFS, ...
- HDU3085NightmareII题解--双向BFS
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3085 分析 大意就是一个男孩和一个女孩在网格里,同时还有两个鬼,男孩每轮走三步,女孩每轮走一步,与鬼曼 ...
随机推荐
- 区间求mex的几种方法
Tags : 总结 莫队 线段树 区间取mex的几种方法 题目大意 无修改,求区间 \(mex\) 做法1 莫队+二分+树状数组 树状数组维护维护桶,每次扫完二分答案,用树状数组判断 \(O(n\sq ...
- FOJ Problem 2256 迷宫
...
- 关于Metadata Client Object Model 的一些操作
一.查询指定的Termset及子项 <script type="text/javascript" src="/Style%20Library/aaaa/Script ...
- 从Java源码到Java字节码
Java最主流的源码编译器,javac,基本上不对代码做优化,只会做少量由Java语言规范要求或推荐的优化:也不做任何混淆,包括名字混淆或控制流混淆这些都不做.这使得javac生成的代码能很好的维持与 ...
- Codeforces 842C Ilya And The Tree 树上gcd
题目链接 题意 给定一棵根为\(1\)的树.定义每个点的美丽值为根节点到它的路径上所有点的\(gcd\)值.但是对于每个点,在计算它的美丽值时,可以将这条路径上某个点的值变为\(0\)来最大化它的美丽 ...
- Scrapy学习-15-降低被识别为爬虫的方法
3种常见的方法 1. 在settings中配置禁用cookies COOKIES_ENABLED = False 2. scrapy限速处理,scrapy为我们提供了扩展模块,它能动态的限制下载速度 ...
- python笔记3:注释命名风格
6.注释: 行注释采用 # 开头,多行注释使用三个单引号 (''') 或三个双引号 ("' '"),注释不需要对齐 三引号让程序员从引号和特殊字符串的泥潭里面解脱出来,自始至终保 ...
- Powershell简介及其编程访问
Powershell是下一代的命令行外壳程序,较之于它的前身(cmd.exe),它的功能更加强大,也更加易用.最根本的区别在于它是基于对象的操作(基于.NET Framework),而不是基于字符串的 ...
- FMDB使用Cached Statement功能
FMDB使用Cached Statement功能 在FMDB中,Cached Statement功能是一种提高SQLite数据库访问的技术.在SQLite中,所有的SQL语句都会被编译,形成预处理 ...
- 1005 Spell It Right
1005 Spell It Right Given a non-negative integer N, your task is to compute the sum of all the dig ...