#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. Altium Designer打印多块PCB到热转印纸上、拼板发给工厂

    接下来介绍的方法的优势有: 节省电脑性能(来自不同PCB文件的图案被放置时只在第1块会卡顿一小会儿,之后不再卡顿) 便于排版(拖放图案时绝不会改变图案内容,拖放图案时鼠标拖住的矩形框的尺寸与图案的尺寸 ...

  2. 五种编程语言解释数据结构与算法——顺序表1(理论与C语言实现)

    1.线性表的分类 2.线性表的定义及其基本操作 2.1.定义:线性表是具有相同类型的n(n>=0)个元素的有序序列,其中n为表长,当n=0时,该表为空表. 2.3.线性表的逻辑结构为: 2.4. ...

  3. [Effective Java 读书笔记] 第二章 创建和销毁对象 第二条

    第二条 遇到多个构造器参数时,可以考虑用构建器 当遇到有多个构造器参数时,常见的是用重叠构造器,即: public class TestClass{ public TestClass(int para ...

  4. Integer缓存机制-基本数据类型和包装类型-自动拆装箱

    Integer缓存机制 总结: 1.jdk1.5对Integer新增了缓存机制,范围在-128-127(这个范围的整数值使用频率最高)内的自动装箱返回的是缓存对象,不会new新的对象,所以只要在缓存范 ...

  5. vux-- Vue.js 移动端 UI 组件库

    1.使用 安装或更新: npm install vux --save npm install vux-loader --save 如果没有安装less: npm install less less-l ...

  6. Java的引用类型的内存分析

    一. jdk的内存:jdk的bin目录常见命令 1. javac.exe:编译java源代码的,生成java字节码文件(*.class) 2. java.exe:启动一个jvm,来运行指定class字 ...

  7. XPath简介、功能及使用方法

    html = '''<html><head><title>The Dormouse's story</title></head><bo ...

  8. 试题 基础练习 Huffuman树

    试题 基础练习 Huffuman树 试题 基础练习 Huffuman树 ​ 翻了翻网上,基本都是暴力排序.我就提供一个最小堆的写法吧! ​ 点击这里,跳转查看最小堆插入删除函数的简单写法 Talk i ...

  9. 【HDU - 1029】Ignatius and the Princess IV (水题)

    Ignatius and the Princess IV  先搬中文 Descriptions:   给你n个数字,你需要找出出现至少(n+1)/2次的数字 现在需要你找出这个数字是多少? Input ...

  10. 二、GLTF模型支持

    1.安装ColladaToGltf.exe 2. @echo off cd C:\Users\wangc04\Desktop\daeconverting\ColladaToGltfcollada2gl ...