问题 1672: 迷宫问题
时间限制: 1Sec 内存限制: 32MB
题目描述
小明置身于一个迷宫,请你帮小明找出从起点到终点有多少种走法。
小明只能向上下左右四个方向移动。
输入
输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是两个整数N和M(1<=N,M<=100)。
接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。
字符的含义如下:
‘s’:起点
‘e’:终点
‘-.:空地,可以通过
‘#’:障碍,无法通过
输入数据保证有且仅有一个起点和终点。
输出
对于每组输入,输出多少中走法,如果不存在从起点到终点的路,则输出-1。
样例输入:
样例输出:
1
分析:利用深搜统计即可
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int m,n;
int ans=0;//记录次数
bool vis[1005][1005];
int dir[4][2]{{-1,0},{0,-1},{1,0},{0,1}};
string mp[1005];
bool in(int x,int y){
return x>=0&&x<m&&y>=0&&y<n;
}
void dfs(int x,int y){
if(mp[x][y]=='e'){
ans++;
return;
}
vis[x][y]=true;
for(int i=0;i<4;i++){
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if(in(tx,ty)&&!vis[tx][ty]&&mp[tx][ty]!='#'){
dfs(tx,ty);
}
}
vis[x][y]=false;
}
int main(){
cin>>m>>n;
int x,y;
for(int i=0;i<m;i++){
cin>>mp[i];
}
for(int i=0;i<m;i++){//找到起点
for(int j=0;j<n;j++){
if(mp[i][j]=='s'){
x=i;
y=j;
}
}
}
dfs(x,y);
if(ans>0)
cout<<ans<<endl;
else
printf("-1");
return 0;
}
运行结果:
接来来是问最小步数数多少(这里用到了搜索剪枝)
#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
int n,m;
string maze[110];
bool vis[110][110];
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int ans=100000;
bool in (int x,int y){
return 0<=x&&x<n&&0<=y&&y<m;
}
void dfs(int x,int y,int step){
if(step>=ans){//这里是剪枝,当大于这个步数时,我们就无需再进行这条路找下去了
return;
}
if(maze[x][y]=='T'){
ans=step;
return;
}
vis[x][y]=true;
for(int i=0;i<4;i++){
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if(in(tx,ty)&&maze[tx][ty]!='#'&&!(vis[tx][ty])){
dfs(tx,ty,step+1);
}
}
vis[x][y]=false;
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>maze[i];
}
int x,y;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(maze[i][j]=='S'){
x=i,y=j;
}
}
}
dfs(x,y,0);
cout<<ans<<endl;
return 0;
}
运行结果:
下面是最小步数用宽搜来实现(起点S,终点T)
#include<iostream>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
string maze[10005];
bool vis[10005][10005];
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int n,m;
//判断是否在地图中函数
bool in(int x,int y){
return 0<=x&&x<n&&0<=y&&y<m;
}
//用结构体记录状态
struct node{
int x,y,d;
node(int xx,int yy,int dd){//使用构造函数
x=xx;
y=yy;
d=dd;
}
};
int bfs(int sx,int sy){
queue<node> q;//定义队列
q.push(node(sx,sy,0));//起点入队
vis[sx][sy]=true;//标记起点访问过
while(!q.empty()){//判断队列是否为空
node now=q.front();
q.pop();
for(int i=0;i<4;i++){//搜索与当前点相邻的点
int tx=now.x+dir[i][0];
int ty=now.y+dir[i][1];
if(in(tx,ty)&&maze[tx][ty]!='#'&&!vis[tx][ty]){//判断相邻点是否合法
if(maze[tx][ty]=='T'){//当找到终点时直接输出
return now.d+1;
}else{
vis[tx][ty]=true;//标记相邻点来过
q.push(node(tx,ty,now.d+1));//去相邻点搜索
}
}
}
}
return -1;//没有找到放回-1
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
maze[i].resize(m);
}//字符串初始化
for(int i=0;i<n;i++){//输入地图
cin>>maze[i];
}
int x,y;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(maze[i][j]=='S'){//找到起点
x=i,y=j;
}
}
}
cout<<bfs(x,y)<<endl;//宽搜
return 0;
}