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进行解空间的遍历.
随机推荐
- 在maven多模块结构中,并且使用overlay的情况下使用jetty热部署
在使用maven多模块的结构的时候,同时有多个web工程使用maven-war-plugin的overlay来组织的时候,本地开发时如何在eclipse里面启动容器并且可以热部署调试是个比较麻烦的问题 ...
- svn upgrade
在我们把我们服务器上的svn 版本号升级以后,我们之前的代码再执行svn命令时,会提示需要执行svn upgrade命令把当前的代码由低版本的svn 上迁移到高版本的svn 上去. 直接执行svn u ...
- sas教程
http://web5.pku.edu.cn/pucssr/SASbiancheng.pdf 本教程中的主题将向您介绍 SAS Enterprise Guide.您最好依次浏览这些主题. 概述 启动项 ...
- Spring → 03:核心机制
一.控制反转 1.1.控制反转的概念 (1).Inverse of Controller被称为控制反转或反向控制,其实真正体现的是“控制转移”.(2).所谓的控制指的是负责对象关系的指定.对象创建.初 ...
- Apache Camel继承Spring Boot 实现文件远程复制和转移
pom.xml <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-f ...
- @codeforces - 932G@ Palindrome Partition
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个字符串 s,求有多少种方案可将其划分成偶数个段 \(p_ ...
- rqnoj86 智捅马蜂窝
题目描述 背景 为了统计小球的方案数,平平已经累坏了.于是,他摘掉了他那800度的眼镜,躺在树下休息. 后来,平平发现树上有一个特别不一样的水果,又累又饿的平平打算去把它摘下来. 题目描述 现在,将大 ...
- Selenium-----wait的三种等待
在UI自动化测试中,必然会遇到环境不稳定,网络慢的情况,这时如果你不做任何处理的话,代码会由于没有找到元素,而报错.这时我们就要用到wait(等待),而在Selenium中,我们可以用到一共三种等待, ...
- Python3 写的远程批量修改文件内容的脚本
一.说明: 1.利用Python的paramiko模块,调用远程的shell命令去修改相应文件. 2.有一个专用配置文件,列出服务器清单. 3.Python循环读取配置文件的服务器IP去连接它,并执行 ...
- Effective C++: 01让自己习惯C++
01:视C++为一个语言联邦 1:今天的C++已经是个多重范型编程语言(multiparadigm programming language),一个同时支持过程形式(procedural).面向对象形 ...