Codevs 2855 游乐园的迷宫
2855 游乐园的迷宫
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold
题目描述 Description
迷宫可是每个游乐园必不可少的项目,菜菜当然是要尝试一下啦。
这个迷宫比较特殊。与其说是迷宫,倒不如说是一个巨大的格子。游乐园给菜菜发了一张地图,地图上标明了,这个格子由n行m列共n*m个小格子组成。有的格子可以正常走,标为’.’;有的格子有陷阱不能走,标为‘#’;有的格子比较特殊,标为‘*’,可以向周围八个方向可走的格子走一格;目的地标记为‘@’。菜菜从左上角处开始,并且可以按中国象棋中的马和象的方式或者特殊格的八方向来走。如果按照最短的路径到达目的地,则可以获得奖励。
菜菜当然想获得奖励啦,于是就来找你帮忙,请你帮忙计算最少需要多少步。
输入描述 Input Description
第一行,两个正整数n,m。
接下来的n行m列描述了地图。
输出描述 Output Description
一个整数,表示所要走的最小步数。若无法到达目的地则输出-1。
样例输入 Sample Input
11 10
..........
....#.....
..........
...#.*....
.......*..
..#..#...@
*.........
...#...#..
.....*....
...#......
..*....*..
样例输出 Sample Output
13
数据范围及提示 Data Size & Hint
对于20%的数据,保证0<n,m≤20
对于100%的数据,保证0<n,m≤200
50分代码存档:
1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<queue>
5 using namespace std;
6 #define maxn 205
7 int n,m,dis[maxn][maxn],ex,ey;
8 int dx[]={-2,-2,-2,-2,-1,-1,+1,+1,+2,+2,+2,+2};
9 int dy[]={-2,-1,+1,-2,+2,+2,-2,+2,-2,-1,+1,+2};
10 int bax[]={-1,-1,-1,0,0,1,1,1};
11 int bay[]={-1,0,1,-1,1,-1,0,1};
12 char map[maxn][maxn];
13 queue<int> stx,sty;
14 bool vis[maxn][maxn];
15 bool Judge(int xx,int yy){
16 if(xx>0&&xx<=n&&yy>0&&yy<=m&&map[xx][yy]!='#'&&!vis[xx][yy])
17 return true;
18 else return false;
19 }
20 void BFS(){
21 stx.push(1);sty.push(1);
22 while(!stx.empty()){
23 int nx=stx.front(),ny=sty.front();
24 stx.pop();sty.pop();
25 if(map[nx][ny]=='.'){
26 for(int i=0;i<12;i++){
27 int xx=nx+dx[i],yy=ny+dy[i];
28 if(Judge(xx,yy)){
29 stx.push(xx);sty.push(yy);vis[xx][yy]=true;
30 dis[xx][yy]=min(dis[xx][yy],dis[nx][ny]+1);
31 if(xx==ex&&yy==ey) return;
32 }
33 }
34 }
35 else if(map[nx][ny]=='*'){
36 for(int i=0;i<8;i++){
37 int xx=nx+dx[i],yy=ny+dy[i];
38 if(Judge(xx,yy)){
39 stx.push(xx);sty.push(yy);vis[xx][yy]=true;
40 dis[xx][yy]=min(dis[xx][yy],dis[nx][ny]+1);
41 if(xx==ex&&yy==ey) return;
42 }
43 }
44 }
45 }
46 }
47 int main()
48 {
49 memset(dis,0x3f,sizeof(dis));
50 scanf("%d%d",&n,&m);
51 for(int i=1;i<=n;i++)
52 for(int j=1;j<=m;j++){
53 cin>>map[i][j];
54 if(map[i][j]=='@') ex=i,ey=j;
55 }
56 dis[1][1]=0;
57 BFS();
58 if(dis[ex][ey]==0x3f) printf("-1\n");
59 else printf("%d\n",dis[ex][ey]);
60 return 0;
61 }
AC代码:
1 #include<iostream>
2 #include<bits/stdc++.h>
3 using namespace std;
4 const int maxN = 205;
5 char maze[maxN][maxN];
6 int n,m;
7 int dx,dy;
8 bool vis[maxN][maxN];
9 struct Node {
10 int x,y;
11 int dep;//记录步数
12 };
13 bool is_raw(int x,int y) {
14 if(x >= 1 && x <= n && y >= 1 && y <= m && maze[x][y] != '#') return true;
15 return false;
16 }
17 bool ok = false;
18 int dir[24]= {1,2,1,-2, -1,2,-1,-2, 2,1,2,-1, -2,-1,-2,1, //马
19 2,-2,-2,2,-2,-2,2,2};//象
20 int spec[16] = {-1,0,-1,-1,-1,1, 1,-1,1,1,1,0, 0,1,0,-1};//九宫格
21 int ans = 0;
22 void bfs() { //找最小,宽搜罗~
23 Node start;
24 start.x = 1, start.y = 1;
25 start.dep = 0;
26 queue<Node> q;
27 q.push(start);
28 while(!q.empty()) {
29 Node head = q.front();
30 //printf("x is %d, y is %d , dep is %d \n",head.x,head.y,head.dep);
31 if(head.x == dx && head.y == dy) {
32 ok = true;
33 ans = head.dep;
34 return;
35 }
36 q.pop();
37 for(int i = 0 ; i < 24; i = i + 2) {
38 if(is_raw(head.x+dir[i],head.y+dir[i+1])&&
39 !vis[head.x+dir[i]][head.y+dir[i+1]]) {
40 Node one;
41 vis[head.x+dir[i]][head.y+dir[i+1]] = true;
42 one.x = head.x+dir[i];
43 one.y = head.y+dir[i+1];
44 one.dep = head.dep+1;
45 q.push(one);
46 }
47 }
48 if(maze[head.x][head.y] == '*') {
49 for(int i = 0 ; i < 16; i = i + 2) {
50 if(is_raw(head.x+spec[i],head.y+spec[i+1])&&
51 !vis[head.x+spec[i]][head.y+spec[i+1]]) {
52 Node one;
53 vis[head.x+spec[i]][head.y+spec[i+1]] = true;
54 one.x = head.x+spec[i];
55 one.y = head.y+spec[i+1];
56 one.dep = head.dep+1;
57 q.push(one);
58 }
59 }
60 }
61 }
62 }
63 int main() {
64 cin>>n>>m;
65 memset(vis,0,sizeof(vis));
66 for(int i = 1 ; i <= n ; i++) {
67 for(int j = 1 ; j <= m; j++) {
68 cin>>maze[i][j];
69 if(maze[i][j] == '@')
70 dx = i,dy = j;
71 }
72 }
73 //printf("目标是 %d %d\n",dx,dy);
74 bfs();
75 if(ok) printf("%d\n",ans);
76 else cout<<"-1"<<endl;
77 }
//话说这题样例有问题,被样例坑了好长时间.......
再次AC代码:
/* 再次AC代码。。我日,我说咋回事吗,我感觉我写的也没什么 毛病就是不对挨!原来是题意理解错误 对于那些特殊的点既能够 按照八方向来走 ,也能够按照 普通点的 方向来走,刚开始写的时候 把两类点分开 写的。。。 */ #include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; #define maxn 205 int n,m,dis[maxn][maxn],ex,ey; int dx[]={-2,-2,-2,-2,-1,-1,+1,+1,+2,+2,+2,+2}; int dy[]={-2,-1,+1,-2,+2,+2,-2,+2,-2,-1,+1,+2}; int bax[]={-1,-1,-1,0,0,1,1,1}; int bay[]={-1,0,1,-1,1,-1,0,1}; char map[maxn][maxn]; queue<int> stx,sty; bool vis[maxn][maxn]; bool Judge(int xx,int yy){ if(xx>0&&xx<=n&&yy>0&&yy<=m&&map[xx][yy]!='#'&&!vis[xx][yy]) return true; else return false; } void BFS(){ stx.push(1);sty.push(1); while(!stx.empty()){ int nx=stx.front(),ny=sty.front(); stx.pop();sty.pop(); for(int i=0;i<12;i++){ int xx=nx+dx[i],yy=ny+dy[i]; if(Judge(xx,yy)){ stx.push(xx);sty.push(yy);vis[xx][yy]=true; dis[xx][yy]=min(dis[xx][yy],dis[nx][ny]+1); if(xx==ex&&yy==ey) return; } } if(map[nx][ny]=='*'){ for(int i=0;i<8;i++){ int xx=nx+dx[i],yy=ny+dy[i]; if(Judge(xx,yy)){ stx.push(xx);sty.push(yy);vis[xx][yy]=true; dis[xx][yy]=min(dis[xx][yy],dis[nx][ny]+1); if(xx==ex&&yy==ey) return; } } } } } int main() { memset(dis,0x3f,sizeof(dis)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ cin>>map[i][j]; if(map[i][j]=='@') ex=i,ey=j; } dis[1][1]=0; BFS(); if(dis[ex][ey]>=1500000) printf("-1\n"); else printf("%d\n",dis[ex][ey]); return 0; }