UVa 1601 万圣节后的早晨
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4476
题意:给出w*h的网格,相当于迷宫,有大写字母和小写字母,算出小写字母走到大写字母状态时的最少步数。
思路:建立新图,然后再bfs。
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
using namespace std; const int maxn = * ; char map[][];
int w, h, n;
int cnt; //非#结点个数
int x[maxn], y[maxn];
int s[], t[]; //记录初末位置
int deg[maxn]; //记录每个格子相连的格子数
int G[maxn][maxn]; //记录每个格子可以走的位置
int new_map[][]; //新图
int d[maxn][maxn][maxn]; //记录步数 int dx[] = { , , -, , };
int dy[] = { , , , , - }; int ID(int x, int y, int z) //二进制压缩存储,方便进出队列
{
return (x << ) | (y << ) | z;
} bool judge(int a, int b, int a2, int b2)
{
return a2 == b2 || (a2 == b && b2 == a);
} void 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; //得到压缩前的数据
int b = (u >> ) & 0xff;
int c = u & 0xff;
if (a==t[] && b==t[] && c==t[]) //得到目标状态
{
cout << d[a][b][c] << endl;
return;
}
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 (judge(a, b, a2, b2)) continue; //删去不符合条件的走法
for (int k = ; k < deg[c]; k++)
{
int c2 = G[c][k];
if (judge(a, c, a2, c2)) continue;
if (judge(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));
}
}
}
}
} int main()
{
//freopen("D:\\txt.txt", "r", stdin);
while (cin>>w>>h>>n && n)
{
getchar();
cnt = ; //记录非#结点个数
memset(map, , sizeof(map));
memset(deg, , sizeof(deg));
for (int i = ; i < h; i++)
{
fgets(map[i], , stdin);
for (int j = ; j < w; j++)
{
if (map[i][j] != '#')
{
x[cnt] = i;
y[cnt] = j;
new_map[i][j] = cnt; //建图记录结点
if (map[i][j] >= 'a' && map[i][j] <= 'c') s[map[i][j] - 'a'] = cnt;
if (map[i][j] >= 'A' && map[i][j] <= 'C') t[map[i][j] - 'A'] = cnt;
cnt++;
}
}
} for (int i = ; i < cnt; i++)
{
for (int k = ; k < ; k++)
{
int xx = x[i] + dx[k];
int yy = y[i] + dy[k];
if (map[xx][yy] != '#') G[i][deg[i]++] = new_map[xx][yy]; //如果可以走,则将第i个点的第deg[i]个方向的下一个格子记录
}
} //如果不满三个鬼,强行添加结点使之构成三个结点 if (n <= ) //添加虚拟结点
{
deg[cnt] = ; G[cnt][] = cnt; s[] = t[] = cnt++;
}
if (n <= )
{
deg[cnt] = ; G[cnt][] = cnt; s[] = t[] = cnt++;
} bfs();
}
return ;
}
UVa 1601 万圣节后的早晨的更多相关文章
- 万圣节后的早晨&&九数码游戏——双向广搜
https://www.luogu.org/problemnew/show/P1778 https://www.luogu.org/problemnew/show/P2578 双向广搜. 有固定起点终 ...
- uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)
这题数据大容易TLE 优化:预处理, 可以先枚举出5^3的状态然后判断合不合法,但是由于题目说了有很多墙壁,实际上没有那么多要转移的状态那么可以把底图抽出来,然后3个ghost在上面跑到时候就不必判断 ...
- <<操作,&0xff以及|的巧妙运用(以POJ3523---The Morning after Halloween(UVa 1601)为例)
<<表示左移,如a<<1表示将a的二进制左移一位,加一个0,&0xff表示取最后8个字节,如a&0xff表示取a表示的二进制中最后8个数字组成一个新的二进制数, ...
- UVA 1601 The Morning after Halloween
题意: 给出一个最大为16×16的迷宫图和至多3个ghost的起始位置和目标位置,求最少经过几轮移动可以使三个ghost都到达目标位置.每轮移动中,每个ghost可以走一步,也可以原地不动,需要注意的 ...
- UVA - 1601 The Morning after Halloween (BFS/双向BFS/A*)
题目链接 挺有意思但是代码巨恶心的一道最短路搜索题. 因为图中的结点太多,应当首先考虑把隐式图转化成显式图,即对地图中可以相互连通的点之间连边,建立一个新图(由于每步不需要每个鬼都移动,所以每个点需要 ...
- UVA - 1601 The Morning after Halloween (双向BFS&单向BFS)
题目: w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...
- 【Uva 1601】The Morning after Halloween
[Link]: [Description] 给你一张平面图; 最多可能有3只鬼; 给出这几只鬼的初始位置; 然后,这几只鬼有各自的终点; 每秒钟,这几只鬼能同时移动到相邻的4个格子中的一个 任意两只鬼 ...
- UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)
题意 :w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...
- UVA 1601 双向BFS
但是我们还不是很清楚每一次的状态怎么储存?我们可以用一个结构体,将每次的位置存起来,但是这个程序中用了一个更好的储存方法:我们知道最大的格数是16*16个,也就是256个,那么我们转换为二进制表示就是 ...
随机推荐
- java-mybaits-011-mybatis-拦截器计算耗时
实现Mybatis官方提供的拦截器,用于记录SQL语句的执行时间 package com.github.bjlhx15.mybatis; /** * @author lihongxu * @since ...
- Python随机数生成方法
假设你对在Python生成随机数与random模块中最经常使用的几个函数的关系与不懂之处.以下的文章就是对Python生成随机数与random模块中最经常使用的几个函数的关系,希望你会有所收获,以下就 ...
- Civil and Evil Engineer(普林姆)
http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=198#problem/E 水题一道,题意就是让求一遍最小生成树与最大生成树,但我 ...
- ReactNative前端开发者
ReactNative前端开发者 文档版本0.0.2 Author: Necfol 说明: 本文档用于指导前端React Native的开发,如需开发其他其他框架应用,不适用本文档 前期准备 Reac ...
- TFS修改映射路径办法
如果你之前配置好了TFS项目的映射路径.然后每次下载项目都会在你配置的路径,但我们可以修改 方法一:我们可以在 "工作区" 中修改路径
- http协议基础(四)http状态码
一:http状态码 表示客户端http请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作 状态码的类别如下: http状态码种类繁多,大概有60多种,实际上经常使用的只有14种,下面为一 ...
- hexo修改Next主题的样式
Next主题默认对超链接只有下划线样式,很容易被忽略,就想着怎么修改下 主题样式是在\hexoBlog\themes\next\source\css,这里面保存了Muse,Mist和Pisces三个主 ...
- python的数据结构之数字和字符串(四)
一.数字 Python Number 数据类型用于存储数值.数据类型是不允许改变的,这就意味着如果改变 Number 数据类型的值,将重新分配内存空间. Python 支持四种不同的数值类型: 整型( ...
- 又一国产855旗舰突然现身:支持5G
12月28日消息,中国联通官方微博放出了vivo NEX 5G版样机.如图所示,该机搭载骁龙855移动平台及X50 5G调制解调器. 早在8月30日,vivo就宣布完成了面向商用5G智能手机的软硬件开 ...
- MySQL数据库----表与表之间的关系
表1 foreign key 表2 则表1的多条记录对应表2的一条记录,即多对一 利用foreign key的原理我们可以制作两张表的多对多,一对一关系 多对多: 表1的多条记录可以对应表2的一条记录 ...