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 分析 大意就是一个男孩和一个女孩在网格里,同时还有两个鬼,男孩每轮走三步,女孩每轮走一步,与鬼曼 ...
随机推荐
- Java 学习(2):java 基础概念
Java作为一种面向对象语言.支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载 基础语法: 一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.以 ...
- 3D标签
动态实现3D标签, 主要代码: // // XLMatrix.h // XLSphereView // // Created by 史晶晶 on 16/4/4. // Copyright © 2016 ...
- 【NOIP2016练习】T3 subset (分块,状压DP)
3 subset 3.1 题目 述 一开始你有一个空集,集合可以出现重复元素,然后有 Q 个操作 add s 在集合中加入数字 s. del s 在集合中删除数字 s.保证 s 存在 cnt s 查 ...
- LeetCode OJ——Pascal's Triangle
http://oj.leetcode.com/problems/pascals-triangle/ 杨辉三角 先分析数据,找出规律 ans[row][col] = ans[row-1][col-1]+ ...
- js-className修改class属性
1.修改className 1)修改class类名为p-a-0 2)在保留class="p1"的基础上再添加一个类名为p-a-0 2.删除className 1).结果需删除cla ...
- Python递归函数和二分查找算法
递归函数:在一个函数里在调用这个函数本身. 递归的最大深度:998 正如你们刚刚看到的,递归函数如果不受到外力的阻止会一直执行下去.但是我们之前已经说过关于函数调用的问题,每一次函数调用都会产生一个属 ...
- SSH命令总结
目录 一.ssh命令 二.端口转发 三.scp 命令 四.rsync命令 五.sz和rz命令 六. ssh-agent 七.ssh执行命令不退出问题 参考文章 一.ssh命令 登录类型 密码登录: 服 ...
- ELK之收集Java日志、通过TCP收集日志
1.Java日志收集 使用codec的multiline插件实现多行匹配,这是一个可以将多行进行合并的插件,而且可以使用what指定将匹配到的行与前面的行合并还是和后面的行合并. 语法示例: inpu ...
- 笔记-迎难而上之Java基础进阶6
import java.io.*; public class InputStreamDemo{ public static void main(String[] args) throws IOExce ...
- 八卦某 G 的前端开发方式及流程--百度FEX前端nwind信息搜集神技能
他山之石,可以攻玉. 话说本人从毕业到现在一直在某 B 公司工作,前些年折腾过不少开发方式和工具,但总觉得或许有更好的方案,所以很好奇其它公司内部是如何工作的,我曾经浏览过某 Y 公司内部无所不包的 ...