Uva1601 The Morning after Halloween【隐式图bfs+图重建】【例题7-9】
来源:互联网 发布:php虚拟主机销售系统 编辑:程序博客网 时间:2024/06/05 17:35
题目:The Morning after Halloween
题意:有n个鬼(n<=3)从起始位置到终点位置最小需几步。n个鬼可以同时移动,5个移动方向:上、下、左、右、不动。俩个点不可以占同一位置或互相交换。
思路:直接搜索,超时,所以将图中的可走路径抽取出来重建图。
(1)重建图:图中放的是可走路径的编号。分别将可走路径的点作为行,每行代表每个可走路径点对应它的5个方向的可走路径连接起来!
(2)bfs:从起点开始枚举3个鬼即可。因为图已建成每行5个方向的可走路径了,所有不需要在此图再走了!
参考:入门经典-例题7-9-P206 + 其他大神代码
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int maxn = 20;//原图大小const int maxg = 150;//转换图大小const int dx[] = {-1,1,0,0,0};//移动方向const int dy[] = {0,0,-1,1,0};char maze[maxn][maxn];//原图int w,h,n;int G[maxg][5];//转换图int deg[maxg];//每个可走路径点的连接点个数int cnt;//可走路径点总数int s[3],e[3];//起点和终点struct Node{ int a,b,c;//3个鬼 int steps;//步数};void built(){//建图 cnt = 0;//可走路径编号,也是个数 int x[maxg],y[maxg];//记录可走路径的坐标 int id[maxg][maxg];//可走路径编号 for(int i=0;i<h;i++){ for(int j=0;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;//将鬼起始位置的编号记录 if(isupper(maze[i][j])) e[maze[i][j] - 'A'] = cnt;//将鬼终点位置的编号记录 cnt++;//增加编号 } } } //建图:分别将可走路径的点作为行,每行代表每个可走路径点对应它的5个方向的可走路径连接起来! for(int i=0;i<cnt;i++){//可走路径点 deg[i] = 0;//用于记录此点的连接边 for(int j=0;j<5;j++){//5个方向 int tx = x[i] + dx[j],ty = y[i] + dy[j];//移动点 if(maze[tx][ty] != '#') G[i][deg[i]++] = id[tx][ty];//将可走路径连接起来! } } //将小于3个鬼的补充为3个点,因为下面的bfs只写了3个鬼的搜索! if (n<=2){deg[cnt]=1;G[cnt][0]=cnt;s[2] = e[2] = cnt++;} if (n<=1){deg[cnt]=1;G[cnt][0]=cnt;s[1] = e[1] = cnt++;}}bool judge(int a,int b,int ea,int eb){//判断俩个点不能在同一位置,不能互相交换! return ea == eb || (a == eb && b == ea);}queue<Node>Q;int visit[maxg][maxg][maxg];//标记是否访问int bfs(){ memset(visit,0,sizeof(visit)); while(!Q.empty()) Q.pop();//清空 Node start,pre,temp; start.a = s[0],start.b = s[1],start.c = s[2]; start.steps = 0; Q.push(start); while(!Q.empty()){ pre = Q.front();Q.pop(); if(pre.a == e[0] && pre.b == e[1] && pre.c == e[2]) return pre.steps;//已找到 //枚举3个鬼所在当前点所能走到路径 for(int i=0;i<deg[pre.a];i++){ for(int j=0;j<deg[pre.b];j++){ for(int k=0;k<deg[pre.c];k++){ int na = G[pre.a][i],nb = G[pre.b][j],nc = G[pre.c][k]; if(judge(pre.a,pre.b,na,nb) || judge(pre.a,pre.c,na,nc) || judge(pre.b,pre.c,nb,nc)) continue; temp.a = na;temp.b = nb;temp.c = nc; temp.steps = pre.steps + 1; if(!visit[na][nb][nc])Q.push(temp); visit[na][nb][nc] = 1; } } } }return -1;}int main(){ while(scanf("%d%d%d",&w,&h,&n)!=EOF && (w || h || n)){ getchar(); for(int i=0;i<h;i++) fgets(maze[i], 20, stdin); built(); printf("%d\n",bfs()); } return 0;}
0 0
- Uva1601 The Morning after Halloween【隐式图bfs+图重建】【例题7-9】
- 例题7-9 万圣节后的早晨(The Morning after Halloween, Japan 2007, UVa1601)
- UVa1601-The Morning after Halloween
- UVA1601 The Morning after Halloween
- UVa1601 - The Morning after Halloween(单向+双向BFS)
- 例题7-9 UVA - 1601 && POJ 3523 The Morning after Halloween (双向BFS)
- UVa #1601 The Morning after Halloween (例题7-9)
- [Poj3523][Uva1601][Aizu1281] The Morning after Halloween 【A*算法】
- UVa1601 万圣节后的早晨(The Morning after Halloween)
- 1601 - The Morning after Halloween(BFS)
- UVa 1601 The morning after Halloween(单向BFS+双向BFS)
- 隐式图--UVA - 1601 The Morning after Halloween
- UVa 1601 - The Morning after Halloween(单向BFS版)
- UVa 1601 - The Morning after Halloween(双向BFS版)
- UVa 1601:The Morning after Halloween(BFS)
- UVA 1601 The Morning after Halloween (优化BFS)
- 1601 - The Morning after Halloween
- 1601 - The Morning after Halloween
- IOS开发之OC篇(4)—— NSDictionary、NSMutableDictionary
- (@WhiteTaken)设计模式学习——简单工厂模式
- POJ 3393Lucky and Good Months by Gregorian Calendar(模拟)
- 高并发服务端分布式系统设计概要(下)
- Spring Cache原理与使用及ICOP平台中的缓存应用
- Uva1601 The Morning after Halloween【隐式图bfs+图重建】【例题7-9】
- Map遍历的四种方法
- 764A
- MVC模式 (基本理解)
- 从基础开始的异世界生活-----poj1753
- 深入理解Spring事务原理
- android请求连接wifi之后验证密码是否正确的方法
- const的用法小结(转)
- JavaSE 学习参考:循环语句中的break