UVa1601 - The Morning after Halloween [单向bfs]
解题思路:
1.注意到2*2方格中必有一个#,那么最多只有192条通道,可以将所有非‘#’的位置提取出来用邻接表的方式建图,通过bfs搜索目标位置。
2.将三个ghost的位置(a,b,c)作为状态量存储,如果采用邻接矩阵方式存储图,那么转移代价为5*5*5,很容易超时。分析题意可以知道图中结点大部分不是4个方向都能通过,用邻接表可以避免做多余的判断。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxv=; int di[]={,-,,,};
int dj[]={,,,-,}; int vis[maxv+][maxv+][maxv+];
typedef struct {
int p[]={};
int dist=;
}state; vector<int> G[maxv+];
char buff[][];
int id[][]; int w,h,n,vn,ans;
int ghost_ascii[];
state ghost_init_pos,ghost_target_pos; int read(){
memset(vis, , sizeof vis);
memset(ghost_ascii, , sizeof ghost_ascii);
memset(id, , sizeof id);
memset(buff, , sizeof buff);
memset(ghost_init_pos.p, , sizeof ghost_init_pos.p);
memset(ghost_target_pos.p, , sizeof ghost_target_pos.p);
scanf("%d%d%d",&w,&h,&n);
if(w==) return ; fgets(buff[], , stdin); for(int i=;i<h;i++)
fgets(buff[i], , stdin); vn=;
for(int i=;i<h;i++)
for(int j=;j<w;j++)
if(buff[i][j]!='#'){
vn++;
id[i][j]=vn;
}
char ch;
for(int i=;i<h;i++){
for(int j=;j<w;j++){
ch=buff[i][j]; if(ch!='#'){
int cur=id[i][j]; for(int pos=;pos<;pos++){
int x=i+di[pos],y=j+dj[pos];
if(x>=&&x<h&&y>=&&y<w&&id[x][y]){
int pre=id[x][y];
G[cur].push_back(pre);
}
} if(islower(ch)){
for(int k=;k<n;k++)
if(!ghost_ascii[k]||ghost_ascii[k]==ch){
ghost_ascii[k]=ch;
ghost_init_pos.p[k]=cur;
break;
}
}
else if(isupper(ch)){
for(int k=;k<n;k++){
if(!ghost_ascii[k]||ghost_ascii[k]==ch+'a'-'A'){
ghost_ascii[k]=ch+'a'-'A';
ghost_target_pos.p[k]=cur;
break;
}
}
}
}
}
}
return ;
}
bool check(const state& u,const state& u2){ for(int i=;i<n;i++)
for(int j=i+;j<n;j++)
if(u2.p[i]==u2.p[j]) return false; for(int i=;i<n;i++)
for(int j=i+;j<n;j++)
if(u2.p[i]==u.p[j]&&u2.p[j]==u.p[i]) return false;
return true;
}
void update(queue<state>& q,const state& u,int i,int j=,int k=){
state u2;
u2.p[]=G[u.p[]][i];
if(n>=) u2.p[]=G[u.p[]][j];
if(n==) u2.p[]=G[u.p[]][k];
if(!vis[u2.p[]][u2.p[]][u2.p[]]&&check(u, u2)) {
vis[u2.p[]][u2.p[]][u2.p[]]=;
u2.dist=u.dist+;
q.push(u2);
/*
for(int m=0;m<n;m++)
cout<<u.p[m]<<" ";
cout<<" to ";
for(int m=0;m<n;m++)
cout<<u2.p[m]<<" ";
cout<<u2.dist<<endl;
*/
}
}
void solve(){
queue<state> q;
q.push(ghost_init_pos);
vis[ghost_init_pos.p[]][ghost_init_pos.p[]][ghost_init_pos.p[]]=;
while(!q.empty()){
state u=q.front();q.pop(); if(memcmp(u.p,ghost_target_pos.p,sizeof ghost_target_pos.p)==) {
ans=u.dist;
break;
}
for(int i=;i<G[u.p[]].size();i++){
if(n==){
update(q, u, i);
}
else for(int j=;j<G[u.p[]].size();j++){
if(n==){
update(q, u, i,j);
}
else for(int k=;k<G[u.p[]].size();k++){
update(q, u, i,j,k);
}
}
}
}
printf("%d\n",ans);
} int main() {
while(read()){
solve(); for(int i=;i<=maxv;i++)
G[i].clear();
} return ;
}
UVa1601 - The Morning after Halloween [单向bfs]的更多相关文章
- UVA - 1601 The Morning after Halloween (双向BFS&单向BFS)
题目: w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...
- POJ1915Knight Moves(单向BFS + 双向BFS)
题目链接 单向bfs就是水题 #include <iostream> #include <cstring> #include <cstdio> #include & ...
- POJ 1915-Knight Moves (单向BFS && 双向BFS 比)
主题链接:Knight Moves 题意:8个方向的 马跳式走法 ,已知起点 和终点,求最短路 研究了一下双向BFS,不是非常难,和普通的BFS一样.双向BFS只是是从 起点和终点同一时候開始搜索,可 ...
- UVA1601 The Morning afther Halloween
题目大意 w h (w, h <= 16)的网格有 n ( n <= 3) 个小写字母(代表鬼)其余的是‘#’(代表障碍格) 或 ‘ ’(代表空格. 要求把他们移动到对应的大写字母里.每步 ...
- UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)
题意 :w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占 ...
- UVA1601-The Morning after Halloween(双向BFS)
Problem UVA1601-The Morning after Halloween Accept: 289 Submit: 3136 Time Limit: 12000 mSec Problem ...
- BFS总结
能够用 BFS 解决的问题,一定不要用 DFS 去做! 因为用 Recursion 实现的 DFS 可能造成 StackOverflow! (NonRecursion 的 DFS 一来你不会写,二来面 ...
- 【HDU3085】nightmare2 双向BFS
对于搜索树分支很多且有明确起点和终点的情况时,可以采用双向搜索来减小搜索树的大小. 对于双向BFS来说,与单向最大的不同是双向BFS需要按层扩展,表示可能到达的区域.而单向BFS则是按照单个节点进行扩 ...
- Word Ladder(双向BFS)
2018-10-02 23:46:38 问题描述: 问题求解: 显然是个解空间遍历问题,每次修改其中一位,由于步长是1,所以可以使用BFS进行解空间的遍历.
随机推荐
- 国内首个全域边缘节点服务发布,阿里云助力企业把握5G机遇
7月24日,阿里云峰会开发者大会在上海世博中心举办.作为2019年首场最受瞩目的云计算开发者大会,阿里云携一众云计算技术大牛与开发者面对面,探讨各自领域的技术干货与前沿趋势.同时,也发布了多项重大重磅 ...
- ajax请求 400 Bad Request, 然后就没进后台方法!
原因可能是 ajax提交表单的data中实体的字段没有值(表单中无值填充的问题) 导致前台就已经报错了! 需要注意的字段类型 double date int .. 我就是因为这个double , ...
- zend studio打开文件提示unsupported character encoding
zend studio打开文件提示unsupported character encoding,是文件的编码方式错误. 有可能是PHP代码中,charset={CHARSET} ,用了变量的形式调用编 ...
- python批量导出项目依赖包及批量安装的方法
在Python中我们在项目中会用到各种库,自带的自然不必再说,然而如果是三方库,则在进行项目移植时通常需要在新的环境下安装需要的三方库文件,面对较大项目中众多的三方库,可以先将项目依赖库导出到txt文 ...
- 【Leetcode链表】移除链表元素(203)
题目 删除链表中等于给定值 val 的所有节点. 示例: 输入: 1->2->6->3->4->5->6, val = 6 输出: 1->2->3-&g ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十四章:曲面细分阶段
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十四章:曲面细分阶段 代码工程地址: https://github. ...
- 通过JS操作CSS
动态效果如图所示: 第一种实现方法: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- 使用UITextView的dataDetectorTypes实现超链接需要注意的事项!
项目中需要在UITextView上识别URL,手机号码.邮箱地址等等信息.那么就用到了它的dataDetectorTypes属性.我的UITextView加在UITableViewCell上面的,当单 ...
- TIJ——Chapter Thirteen:Strings
String 对象是不可修改的,对于被String 重载的'+' 和'+=' 运算符来说,当你用它们来连接两个String 对象的时候,它在底层并不会对于每一次连接均生成一个String 对象,取而代 ...
- Spring读取mybatis在多个jar包下的的mapper文件
刚开始的时候我的配置文件在同名目录下都是在/mapper下,导致只能读取一个jar中的mapper文件.先解决如下: 1.将mapper文件放在不能放在同名的目录下. 比如:user. ...