问题描述
小鼠a与小鼠b身处一个m×n的迷宫中,如图所示。每一个方格表示迷宫中的一个房间。这m×n个房间中有一些房间是封闭的,不允许任何人进入。在迷宫中任何位置均可沿上,下,左,右4个方向进入未封闭的房间。小鼠a位于迷宫的(p,q)方格中,它必须找出一条通向小鼠b所在的(r,s)方格的路。请帮助小鼠a找出所有通向小鼠b的最短道路。
编程任务
对于给定的小鼠的迷宫,编程计算小鼠a通向小鼠b的所有最短道路。
本题有多组输入数据,你必须处理到EOF为止。
每组数据的第一行有3个正整数n,m,k,分别表示迷宫的行数,列数和封闭的房间数。接下来的k行中,每行2个正整数,表示被封闭的房间所在的行号和列号。最后的2行,每行也有2个正整数,分别表示小鼠a所处的方格(p,q)和小鼠b所处的方格(r,s)。(1≤p,r≤n; 1≤q,s≤m)
每组数据的第一行有3个正整数n,m,k,分别表示迷宫的行数,列数和封闭的房间数。接下来的k行中,每行2个正整数,表示被封闭的房间所在的行号和列号。最后的2行,每行也有2个正整数,分别表示小鼠a所处的方格(p,q)和小鼠b所处的方格(r,s)。(1≤p,r≤n; 1≤q,s≤m)
结果输出
对于每组数据,将计算出的小鼠a通向小鼠b的最短路长度和有多少条不同的最短路输出。每组数据输出两行,第一行是最短路长度;第2行是不同的最短路数。每组输出之间没有空行。
如果小鼠a无法通向小鼠b则输出“No Solution!”。
如果小鼠a无法通向小鼠b则输出“No Solution!”。
8 8 3 3 3 4 5 6 6 2 1 7 7
11 96
分析:
深搜和广搜的完美结合,缺少广搜会超时,缺少深搜会爆栈,可以说这道题做出来之后搜索就掌握的差不多了!
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include<queue>
#define ll long long
#define PI acos(-1)
#define M(n, m) sizeof(n, m, sizeof(n));
const int INF = 2 << 30;
const int maxn = 1e6 + 100;
using namespace std;
int n,m,k,t,t1,d,d1,s,ans,map[1010][1010],v[1010][1010];
int dv[4][2]= {1,0,0,1,0,-1,-1,0};
struct date
{
int x,y,s;//坐标以及到达此处的步数
};
//广搜寻找最短路
int bfs(int x,int y)
{
queue<date>qq;
if(!qq.empty())
qq.pop();
date p,q;
p.x=x;
p.y=y;
p.s=0;
qq.push(p);//起点放入队列
while(!qq.empty())
{
p=qq.front();
if(p.x==d&&p.y==d1)//到达终点,返回所用步数
return p.s;
qq.pop();
for(int i=0; i<4; i++)//循环搜索所有情况
{
q.x=p.x+dv[i][0];
q.y=p.y+dv[i][1];
q.s=p.s+1;
if(q.x>0&&q.y>0&&q.x<=m&&q.y<=n&&!v[q.x][q.y]&&!map[q.x][q.y])
{
qq.push(q);
v[q.x][q.y]=1;
}
}
}
return 0;
}
//深搜寻找最短路的条数
void dfs(int x,int y,int ss)
{
if(ss>s)//注意剪枝,否则超时
return ;
if(abs(d-x)+abs(d1-y)+ss>s)//如果现在所处方位到底终点的坐标之和大于最短路,就没有必要再搜,返回上一层
return;
if(ss==s&&x==d&&y==d1)//如果到达终点,且步数等于最短路的步数,条数加一
{
ans++;
return;
}
for(int i=0; i<4; i++)//循环遍历,搜索所有情况
{
int xx=x+dv[i][0];
int yy=y+dv[i][1];
if(xx>0&&xx<=m&&yy>0&&yy<=n&&!v[xx][yy]&&!map[xx][yy])
{
v[xx][yy]=1;
dfs(xx,yy,ss+1);
v[xx][yy]=0;//回溯
}
}
return ;
}
int main()
{
int i,j;
while(scanf("%d%d%d",&m,&n,&k)!=EOF)
{
int a,b;
memset(map,0,sizeof(map));
for(i=0; i<k; i++)
{
scanf("%d%d",&a,&b);
map[a][b]=1; //标记不可走的方格
}
scanf("%d%d%d%d",&t,&t1,&d,&d1);
memset(v,0,sizeof(v));
s=bfs(t,t1);//广搜寻找最短路
ans=0;
memset(v,0,sizeof(v));
dfs(t,t1,0);//深搜寻找最短路的条数
printf("%d\n%d\n",s,ans);
}
return 0;
}