迷宫问题
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 30441 | Accepted: 17504 |
Description
定义一个二维数组:
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, };
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0
Sample Output
(0, 0) (1, 0) (2, 0) (2, 1) (2, 2) (2, 3) (2, 4) (3, 4) (4, 4)題解:模板bfs,路径打印就一个简单的递归。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
int to[4][2]= {0,1,0,-1,1,0,-1,0};
int mapp[6][6];
int direct[6][6];
struct node
{
int x,y;
node () {};
node (int a,int b)
{
x=a;
y=b;
}
};
int check(int x,int y)
{
if(x<0||x>=5||y<0||y>=5||mapp[x][y])
return 0;
return 1;
}
void print(int x,int y)
{
if(direct[x][y]==-1)
{
printf("(%d, %d)\n",x,y);
return ;
}
int i=direct[x][y];
print(x-to[i][0],y-to[i][1]);
printf("(%d, %d)\n",x,y);
}
void bfs()
{
node t(0,0);
queue<node>q;
q.push(t);
direct[0][0]=-1;
mapp[0][0]=1;
while(!q.empty())
{
node it=q.front();
q.pop();
if(it.x==4&&it.y==4)
{
print(4,4);
return ;
}
for (int i=0; i<4; i++)
{
int xx=it.x+to[i][0];
int yy=it.y+to[i][1];
node next(xx,yy);
if(check(xx,yy))
{
direct[xx][yy]=i;//记录每个位置来的方向
mapp[xx][yy]=1;
q.push(next);
}
}
}
}
int main ()
{
for (int i=0; i<5; i++)
for (int j=0; j<5; j++)
cin>>mapp[i][j];
bfs();
return 0;
}
迷宫寻宝(一)
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
4
- 描述
-
一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个很特别的迷宫,迷宫里有N个编过号的门(N<=5),它们分别被编号为A,B,C,D,E.为了找到宝藏,ACM必须打开门,但是,开门之前必须在迷宫里找到这个打开这个门所需的所有钥匙(每个门都至少有一把钥匙),例如:现在A门有三把钥匙,ACM就必须找全三把钥匙才能打开A门。现在请你编写一个程序来告诉ACM,他能不能顺利的得到宝藏。
- 输入
-
输入可能会有多组测试数据(不超过10组)。
每组测试数据的第一行包含了两个整数M,N(1<N,M<20),分别代表了迷宫的行和列。接下来的M每行有N个字符,描述了迷宫的布局。其中每个字符的含义如下:
.表示可以走的路
S:表示ACM的出发点
G表示宝藏的位置
X表示这里有墙,ACM无法进入或者穿过。
A,B,C,D,E表示这里是门,a,b,c,d,e表示对应大写字母的门上的钥匙。
注意ACM只能在迷宫里向上下左右四个方向移动。
最后,输入0 0表示输入结束。 - 输出
- 每行输出一个YES表示ACM能找到宝藏,输出NO表示ACM找不到宝藏。
- 样例输入
-
4 4 S.X. a.X. ..XG .... 3 4 S.Xa .aXB b.AG 0 0
- 样例输出
-
YES NO
题解:我们先统计整个地图所有不同钥匙的各自的个数,在遍历的过程中自然有机会收集钥匙,若收集全某类钥匙就可以打开此类的门才可以进一步的遍历,直至找到宝藏。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
int n,m,str[6];
int to[4][2]= {0,1,0,-1,1,0,-1,0};
char mapp[25][25];
int vis[25][25];
struct node
{
int x,y;
node () {};
node (int a,int b)
{
x=a;
y=b;
}
} ;
int check(int x,int y)
{
if(x<0||x>=n||y<0||y>=m||vis[x][y]||mapp[x][y]=='X')
return 0;
return 1;
}
int bfs(int x,int y)
{
node t(x,y);
queue<node>q;
q.push(t);
vis[x][y]=1;
while(!q.empty())
{
node it=q.front();
q.pop();
char ch=mapp[it.x][it.y];
if(ch>='A'&&ch<='E')//如果是门
{
if(str[ch-'A'])//钥匙没收集全。若收集全了就可以通过此门。
{
if(q.empty())//能走的地方都搜过了(已经没有之外的可以走了),而且没找到宝藏。
return 0;
q.push(it);//还有其他地方没搜,所以再次放队列中,等搜集全钥匙再来开门。
continue;
}
}
for (int i=0; i<4; i++)
{
int xx=it.x+to[i][0];
int yy=it.y+to[i][1];
node tt(xx,yy);
char ch=mapp[xx][yy];
if(check(xx,yy))
{
if(ch>='a'&&ch<='e')//遇见钥匙
str[ch-'a']--;
else if(ch=='G')//遇见宝藏,直接返回1
return 1;
vis[xx][yy]=1;
q.push(tt);
}
}
}
return 0;
}
int main ()
{
while(cin>>n>>m&&n+m)
{
memset(str,0,sizeof(str));
memset(vis,0,sizeof(vis));
for (int i=0; i<n; i++)
cin>>mapp[i];
int sx=0,sy=0;
for (int i=0; i<n; i++)
for (int j=0; j<m; j++)
if(mapp[i][j]=='S')
{
sx=i;
sy=j;
}
else if(mapp[i][j]>='a'&&mapp[i][j]<='e')//统计出整个地图中不同钥匙的各自数量。
str[mapp[i][j]-'a']++;
if(bfs(sx,sy))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}