#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std; int w, h, n, s[], t[];
char dataset[][];
int G[][], vis[][][], dist[][][];
int deg[];
int dx[] = {, -, , , };//这里包含了不移动的情形
int dy[] = {, , , -, }; inline int ID(int a, int b, int c)
{
return (a << ) | (b << ) | c;
}//一种看起来屌炸天的数据整合方式 inline bool conflict(int a, int b, int a2, int b2)
{
return ((a2 == b2) || (a == b2 && b == a2));
//前者是两者运动到同一位置,后者是两者同时交换位置
} int bfs()
{
queue<int> q;
q.push(ID(s[], s[], s[]));
dist[s[]][s[]][s[]] = ;//dist初始值是-1,这里的0是做标记
while(!q.empty())
{
int u = q.front(); q.pop();
int a = (u >> ) & 0xff, b = (u >> ) & 0xff, c = u & 0xff;
//一种看起来屌炸天的数据整合方式,记住!!
if(a == t[] && b == t[] && c == t[]) return dist[a][b][c];
//a对应了main中的cnt编号,它并没有直接验证横竖坐标而是验证了其编号
for(int i = ; i < deg[a]; i++)
{//deg[a]是cnt编号为a的字母在该点的所有可行的运动方向的个数,遍历所有可行方向
int a2 = G[a][i];
//cnt编号为a的字母运动结果a2
for(int j = ; j < deg[b]; j++)
{
int b2 = G[b][j];
//cnt编号为b的字母运动结果b2
if(conflict(a, b, a2, b2))continue;
//对于产生的运动冲突,由第二个字母做出变换方向的让步
for(int k = ; k < deg[c]; k++)
{
int c2 = G[c][k];
//cnt编号为c的字母运动结果c2
if(conflict(a, c, a2, c2) || conflict(b, c, b2, c2))continue;
if(dist[a2][b2][c2] == -)
{
dist[a2][b2][c2] = dist[a][b][c] + ;
//这是记录步数
q.push(ID(a2, b2, c2));
}
}
}
}
}
return -;
} int main() {
//freopen("input.txt", "r", stdin);
while(~scanf("%d%d%d\n", &w, &h, &n) && n)
{
for(int i = ; i < h; i++) fgets(dataset[i], , stdin);
//输入图
int cnt = , x[], y[], id[][];
for(int i = ; i < h; i++)
for(int j = ; j < w; j++)
{
if(dataset[i][j] != '#')//对于所有的可行动的位置都由一个cnt编号
{
//s->cnt->x与y 这是一种值得借鉴的对应关系
x[cnt] = i; y[cnt] = j; id[i][j] = cnt;//在图中赋予可行动位置唯一的id
if(islower(dataset[i][j])) s[dataset[i][j] - 'a'] = cnt;
else if(isupper(dataset[i][j])) t[dataset[i][j] - 'A'] = cnt;
cnt++;//所有的坐标均被分配到x与y数组中,cnt是唯一的确认,将两个数据映射成了一个数据!!!
}//记录bfs路径的起点与终点的信息 s数组是起点,t数组是终点,
}
for(int i = ; i < cnt; i++)//对应每一个位置
{
deg[i] = ;
for(int j = ; j < ; j++)//对应不同的方向且考虑了不移动的情形
{
int nx = x[i] + dx[j]; int ny = y[i] + dy[j];
if(dataset[nx][ny] != '#') G[i][deg[i]++] = id[nx][ny];
//G[cnt编号][方向]
}
}
//对于所有的位置的每一个可行的方向都记录下来
if(n <= ) { deg[cnt] = ; G[cnt][] = cnt; s[] = t[] = cnt++; }
if(n <= ) { deg[cnt] = ; G[cnt][] = cnt; s[] = t[] = cnt++; }//这里似乎是控制移动对象个数
memset(dist, -, sizeof(dist));
printf("%d\n", bfs());
}
return ;
}

这不是我的代码,这是一个很好的代码,下面有几个方面值得借鉴学习:

1、数据结构设计十分巧妙,仅仅使用普通的数组建立的结构使得数据的查找与变换十分快捷方便

2、利用这个代码中的映射结构,提前准备好每个点可行的方向,这个可以用于平时的bfs或dfs中

UVA1601-双向广度优先搜索的更多相关文章

  1. BFS(三):双向广度优先搜索

    所谓双向广度搜索指的是搜索沿两个方向同时进行:(1)正向搜索:从初始结点向目标结点方向搜索:(2)逆向搜索:从目标结点向初始结点方向搜索:当两个方向的搜索生成同一子结点时终止此搜索过程. 广度双向搜索 ...

  2. 51nod 1444:破坏道路 广度优先搜索

    1444 破坏道路 题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  取消关注 在某一个国家,那儿有n个城市,他们通过 ...

  3. 图的广度优先搜索(BFS)

    把以前写过的图的广度优先搜索分享给大家(C语言版) #include<stdio.h> #include<stdlib.h> #define MAX_VERTEX_NUM 20 ...

  4. 广度优先搜索(BFS)

    定义 维基百科:https://en.wikipedia.org/wiki/Breadth-first_search 给定图G=(V,E)和一个可识别的源结点s,广度优先搜索对图G中的边进行系统性的探 ...

  5. 总结A*,Dijkstra,广度优先搜索,深度优先搜索的复杂度比较

    广度优先搜索(BFS) 1.将头结点放入队列Q中 2.while Q!=空 u出队 遍历u的邻接表中的每个节点v 将v插入队列中 当使用无向图的邻接表时,复杂度为O(V^2) 当使用有向图的邻接表时, ...

  6. ACM题目————图的广度优先搜索

    题目描述 图的广度优先搜索类似于树的按层次遍历,即从某个结点开始,先访问该结点,然后访问该结点的所有邻接点,再依次访问各邻接 点的邻接点.如此进行下去,直到所有的结点都访问为止.在该题中,假定所有的结 ...

  7. SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

    数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...

  8. HDU 1312 Red and Black DFS(深度优先搜索) 和 BFS(广度优先搜索)

    Red and Black Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...

  9. HDU 1241 Oil Deposits DFS(深度优先搜索) 和 BFS(广度优先搜索)

    Oil Deposits Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...

  10. HDU 1242 Rescue (BFS(广度优先搜索))

    Rescue Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

随机推荐

  1. 利用ionic3进行上一行和左一行不动,中间移动的功能

    首先在html中的写法是 <ion-header> <ion-navbar> <ion-title>历史数据</ion-title> </ion- ...

  2. 【Java并发工具类】ReadWriteLock

    前言 前面介绍过ReentrantLock,它实现的是一种标准的互斥锁:每次最多只有一个线程能持有ReentrantLock.这是一种强硬的加锁规则,在某些场景下会限制并发性导致不必要的抑制性能.互斥 ...

  3. 版本控制工具-svn

    两个疑问: 1.什么是版本控制? 2.为什么要用版本控制工具? 银联卡的特征: 1.受保护的 2.受约束的 如何与银联卡对应? 1.个人的代码--口袋里的钱 2.版本控制工具中的代码--银联卡里的钱 ...

  4. MongoDB -> kafka 高性能实时同步(采集)mongodb数据到kafka解决方案

    写这篇博客的目的 让更多的人了解 阿里开源的MongoShake可以很好满足mongodb到kafka高性能高可用实时同步需求(项目地址:https://github.com/alibaba/Mong ...

  5. SpringBoot、Spring MVC报错:Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]

    出现问题的原因: jdbc配置不正确 解决方案: 1.检查是否已添加数据库驱动jar包 2.检查数据库服务是否启动 3.检查数据库配置文件 主要为:dialect,driver_class,url,u ...

  6. Hapi+MySql项目实战数据库操作(四)

    数据库访问 下面以Node的ORM框架Sequelize来操作数据库,Mysql为例. 配置数据库连接信息config/db_config.js: //db_config.js module.expo ...

  7. React中的生命周期函数

    React的生命周期函数 什么是生命周期函数:生命周期函数是指在某一个时刻组件会自动调用执行的函数 Initialization:初始化 执行Constructor,初始state和props Mou ...

  8. webpack性能优化

    Webpack优化打包速度以及性能优化 1.跟上技术的迭代(Node.Npm.Yarn) 2.在尽可能少的模块上应用loader 3.Plugin尽可能精简并确保可靠 4.resolve参数合理配置 ...

  9. css position absolute相对于父元素的设置方式

    手机赚钱怎么赚,给大家推荐一个手机赚钱APP汇总平台:手指乐(http://www.szhile.com/),辛苦搬砖之余用闲余时间动动手指,就可以日赚数百元 大家知道css的position abs ...

  10. BP神经网络拟合给定函数

    近期在准备美赛,因为比赛需要故重新安装了matlab,在里面想尝试一下神将网络工具箱.就找了一个看起来还挺赏心悦目的函数例子练练手: y=1+sin(1+pi*x/4) 针对这个函数,我们首先画出其在 ...