FZU1205 小鼠迷宫问题(搜索)

问题描述
小鼠a与小鼠b身处一个m×n的迷宫中,如图所示。每一个方格表示迷宫中的一个房间。这m×n个房间中有一些房间是封闭的,不允许任何人进入。在迷宫中任何位置均可沿上,下,左,右4个方向进入未封闭的房间。小鼠a位于迷宫的(p,q)方格中,它必须找出一条通向小鼠b所在的(r,s)方格的路。请帮助小鼠a找出所有通向小鼠b的最短道路。

小鼠的迷宫 

编程任务

对于给定的小鼠的迷宫,编程计算小鼠a通向小鼠b的所有最短道路。 
Input
本题有多组输入数据,你必须处理到EOF为止。 
 每组数据的第一行有3个正整数n,m,k,分别表示迷宫的行数,列数和封闭的房间数。接下来的k行中,每行2个正整数,表示被封闭的房间所在的行号和列号。最后的2行,每行也有2个正整数,分别表示小鼠a所处的方格(p,q)和小鼠b所处的方格(r,s)。(1≤p,r≤n; 1≤q,s≤m) 

结果输出

Output
对于每组数据,将计算出的小鼠a通向小鼠b的最短路长度和有多少条不同的最短路输出。每组数据输出两行,第一行是最短路长度;第2行是不同的最短路数。每组输出之间没有空行。 
如果小鼠a无法通向小鼠b则输出“No Solution!”。 
Sample Input
8 8 3
3 3
4 5
6 6
2 1
7 7
Sample Output
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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值