但是我们还不是很清楚每一次的状态怎么储存?我们可以用一个结构体,将每次的位置存起来,但是这个程序中用了一个更好的储存方法:我们知道最大的格数是16*16个,也就是256个,那么我们转换为二进制表示就是8位数,那么我们可以使用24位的二进制表示啊!然后我们再进行解压缩,所以这就是很神奇的地方!

普通BFS

#include<iostream>
#include<string>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<queue>
#include<stack>
#include<sstream>
#include<cstdio>
#define INF 0x3f3f3f3f
//const int maxn = 1e6 + 5;
const double PI = acos(-1.0);
typedef long long ll;
using namespace std; const int maxn = ;
const int maxs = ;
const int dx[] = { ,-,,, };
const int dy[] = { ,,,-, }; inline int ID(int a, int b, int c) {
return (a << ) | (b << ) | c;
} int s[], t[]; int deg[maxn]; //记录每个编号为i的空格周围可以走的步数
int G[maxn][]; inline bool conflict(int a, int b, int a2, int b2) {
return a2 == b2 || (a2 == b && b2 == a);
} int d[maxn][maxn][maxn]; int bfs() {
queue<int> q;
memset(d, -, sizeof d);
q.push(ID(s[], s[], s[]));
d[s[]][s[]][s[]] = ;
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 d[a][b][c];
for (int i = ; i < deg[a]; i++) {
int a2 = G[a][i];
for (int j = ; j < deg[b]; j++) {
int b2 = G[b][j];
if (conflict(a, b, a2, b2)) continue;
for (int k = ; k < deg[c]; k++) {
int c2 = G[c][k];
if (conflict(a, c, a2, c2)) continue;
if (conflict(b, c, b2, c2)) continue;
if (d[a2][b2][c2] != -) continue;
d[a2][b2][c2] = d[a][b][c] + ;
q.push(ID(a2, b2, c2));
}
}
}
}
return -;
} int main() {
int w, h, n; while (scanf("%d%d%d", &w, &h, &n) == && n) {
char maze[][];
for (int i = ; i < h; i++) fgets(maze[i], , stdin); int cnt, x[maxn], y[maxn], id[maxs][maxs];
cnt = ;
for (int i = ; i < h; i++) {
for(int j=;j<w;j++)
if (maze[i][j] != '#') {
x[cnt] = i;
y[cnt] = j;
id[i][j] = cnt;
if (islower(maze[i][j])) s[maze[i][j] - 'a'] = cnt;
else if (isupper(maze[i][j])) t[maze[i][j] - 'A'] = cnt;
cnt++;
}
} for (int i = ; i < cnt; i++) {
deg[i] = ;
for (int dir = ; dir < ; dir++) {
int xx = x[i] + dx[dir], yy = y[i] + dy[dir];
if (maze[xx][yy] != '#') G[i][deg[i]++] = id[xx][yy];
}
} if (n <= ) {
deg[cnt] = ;
G[cnt][] = cnt;
s[] = t[] = cnt++;
}
if (n <= ) {
deg[cnt] = ;
G[cnt][] = cnt;
s[] = t[] = cnt++;
} printf("%d\n", bfs()); }
return ;
}

双向BFS

#include<iostream>
#include<string>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<queue>
#include<stack>
#include<sstream>
#include<cstdio>
#define INF 0x3f3f3f3f
//const int maxn = 1e6 + 5;
const double PI = acos(-1.0);
typedef long long ll;
using namespace std; const int maxn = ;
const int maxs = ;
const int dx[] = { ,-,,, };
const int dy[] = { ,,,-, }; inline int ID(int a, int b, int c) {
return (a << ) | (b << ) | c;
} int s[], t[]; int deg[maxn]; //记录每个编号为i的空格周围可以走的步数
int G[maxn][];
char maze[maxn][maxn];
int color[maxn][maxn][maxn]; inline bool conflict(int a, int b, int a2, int b2) {
//两个鬼是exchange位置(违反第2条)
//两个鬼移动到同一个格子(违反第1条)
return a2 == b2 || (a2 == b && b2 == a);
} int d1[maxn][maxn][maxn]; int bfs() {
queue<int> qf;
queue<int> qb; d1[s[]][s[]][s[]] = ;
d1[t[]][t[]][t[]] = ; qf.push(ID(s[], s[], s[]));
qb.push(ID(t[], t[], t[])); while (!qf.empty() || !qb.empty()) {
int fnum = qf.size(), bnum = qb.size();
while (fnum--) {
int u = qf.front(); qf.pop();
int a = (u >> ) & 0xff, b = (u >> ) & 0xff, c = u & 0xff; for (int i = ; i < deg[a]; i++) {
int a2 = G[a][i];
for (int j = ; j < deg[b]; j++) {
int b2 = G[b][j];
if (conflict(a, b, a2, b2)) continue;
for (int k = ; k < deg[c]; k++) {
int c2 = G[c][k];
if (conflict(a, c, a2, c2) || conflict(b, c, b2, c2)) continue;
if (color[a2][b2][c2] == ) {
d1[a2][b2][c2] = d1[a][b][c] + ;
color[a2][b2][c2] = ;
qf.push(ID(a2, b2, c2));
}
else if (color[a2][b2][c2] == ) {
return d1[a][b][c] + d1[a2][b2][c2];
}
}
}
}
}
while (bnum--) {
int u = qb.front(); qb.pop();
int a = (u >> ) & 0xff, b = (u >> ) & 0xff, c = u & 0xff; for (int i = ; i < deg[a]; i++) {
int a2 = G[a][i];
for (int j = ; j < deg[b]; j++) {
int b2 = G[b][j];
if (conflict(a, b, a2, b2)) continue;
for (int k = ; k < deg[c]; k++) {
int c2 = G[c][k];
if (conflict(a, c, a2, c2) || conflict(b, c, b2, c2)) continue;
if (color[a2][b2][c2] == ) {
d1[a2][b2][c2] = d1[a][b][c] + ;
color[a2][b2][c2] = ;
qb.push(ID(a2, b2, c2));
}
else if (color[a2][b2][c2] == ) {
return d1[a][b][c] + d1[a2][b2][c2];
}
}
}
}
}
}
return -;
} int main() {
int w, h, n;
while (scanf("%d%d%d", &w, &h, &n) == , n) {
for (int i = ; i < h; i++) fgets(maze[i], , stdin);
int cnt = ;
int x[maxn], y[maxn];
int id[maxs][maxs];
for (int i = ; i < h; i++) {
for (int j = ; j < w; j++) {
if (maze[i][j] != '#') {
x[cnt] = i, y[cnt] = j, id[i][j] = cnt;
if (islower(maze[i][j])) s[maze[i][j] - 'a'] = cnt;
else if (isupper(maze[i][j])) t[maze[i][j] - 'A'] = cnt;
cnt++;
}
}
} for (int i = ; i < cnt; i++) {
for (int j = ; j < ; j++) {
int xx = x[i] + dx[j], yy = y[i] + dy[j];
if (maze[xx][yy] != '#') G[i][deg[i]++] = id[xx][yy];
}
} if (n <= ) {
deg[cnt] = ;
G[cnt][] = cnt;
s[] = t[] = cnt++;
}
if (n <= ) {
deg[cnt] = ;
G[cnt][] = cnt;
s[] = t[] = cnt++;
} memset(d1, , sizeof d1);
memset(color, , sizeof color); if (s[] == t[] && s[] == t[] && s[] == t[]) printf("0\n");
else printf("%d\n", bfs());
}
return ;
}

UVA 1601 双向BFS的更多相关文章

  1. 【UVa】1601 The Morning after Halloween(双向bfs)

    题目 题目     分析 双向bfs,对着书打的,我还调了好久.     代码 #include<cstdio> #include<cstring> #include<c ...

  2. UVA - 1601 The Morning after Halloween (双向BFS&单向BFS)

    题目: w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...

  3. UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)

    题意 :w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...

  4. UVA - 11624 Fire! 双向BFS追击问题

    Fire! Joe works in a maze. Unfortunately, portions of the maze have caught on fire, and the owner of ...

  5. <<操作,&0xff以及|的巧妙运用(以POJ3523---The Morning after Halloween(UVa 1601)为例)

    <<表示左移,如a<<1表示将a的二进制左移一位,加一个0,&0xff表示取最后8个字节,如a&0xff表示取a表示的二进制中最后8个数字组成一个新的二进制数, ...

  6. POJ1915Knight Moves(单向BFS + 双向BFS)

    题目链接 单向bfs就是水题 #include <iostream> #include <cstring> #include <cstdio> #include & ...

  7. HDU 3085 Nightmare II 双向bfs 难度:2

    http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...

  8. POJ 3170 Knights of Ni (暴力,双向BFS)

    题意:一个人要从2先走到4再走到3,计算最少路径. 析:其实这个题很水的,就是要注意,在没有到4之前是不能经过3的,一点要注意.其他的就比较简单了,就是一个双向BFS,先从2搜到4,再从3到搜到4, ...

  9. [转] 搜索之双向BFS

    转自:http://www.cppblog.com/Yuan/archive/2011/02/23/140553.aspx 如果目标也已知的话,用双向BFS能很大程度上提高速度. 单向时,是 b^le ...

随机推荐

  1. js--滑动块

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  2. Manacher(马拉车)算法

    Manacher算法是一个求字符串的最长回文子串一种非常高效的方法,其时间复杂度为O(n).下面分析以下其实行原理及代码: 1.首先对字符串进行预处理 因为回文分为奇回文和偶回文,分类处理比较麻烦,所 ...

  3. Simple English

    Simple English 1. Basic English 1.1 设计原则: 1.2 基本英语单词列表850个 1.3 规则: 1.4 质疑 1.5 维基百科:基本英语组合词表 1.6 简单英文 ...

  4. [经验] SpringBoot 远程连接 Linux 上的 Redis

    开发环境: ---------- springboot 2.X ---------- Linux Ubuntu 18.0.04 关于怎么在 Ubuntu 上安装 Linux , 网上的教程一大堆, 这 ...

  5. request和response对象如何解决中文乱码问题?

    出现中文乱码的问题,一般的原因编码和和解码不一致造成的. /* 乱码:编码和解码不一致导致的 GET:你好 POST:?????? tomcat版本:8.5及以上版本 GET请求方式,request对 ...

  6. eslint检测规则中,括弧和函数名之间去掉空格的配置

    在.eslintrc.js中配置: // add your custom rules here rules: { // no space before function name "spac ...

  7. uniGUI之新窗口uniForm(19)

    然后 保存,在这里 重命名窗口 //主窗口 调用 // NewForm2.UniForm1.Show() ; //非阻塞 NewForm2.UniForm1.ShowModal();//阻塞 //子窗 ...

  8. 如何用AU3调用自己用VC++写的dll函数

    这问题困扰我一个上午了,终于找到原因了,不敢藏私,和大家分享一下. 大家都知道,AU3下调用dll文件里的函数是很方便的,只要一个dllcall语句就可以了. 比如下面这个: $result = Dl ...

  9. Xcode 9.0 报错,Safe Area Layout Guide Before IOS 9.0

    解决方案就是: 第一步 第二步 第三步 重新编译.

  10. zabbix server 安装部署

    一:安装zabbix服务端 1.部署准备 命令:iptables -F     #关闭防火墙命令:systemctl stop firewalld    #关闭防火墙 设置解析,自建yum源 命令:c ...