小鼠迷宫问题

FJNU.1354 & 1981

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


对于给定的小鼠的迷宫,编程计算小鼠a通向小鼠b的所有最短道路。

Input
第一行有3个正整数n,m,k,分别表示迷宫的行数,列数和封闭的房间数。接下来的k行中,每行2个正整数,表示被封闭的房间所在的行号和列号。最后的2行,每行也有2个正整数,分别表示小鼠a所处的方格(p,q)和小鼠b所处的方格(r,s)。

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

Source
Fujian OI -- 2005

My Program

#include < stdio.h >
#define  N 60
int  s,map[N + 1 ][N + 1 ];
typedef 
struct {
    
int x,y;
}
xy;
xy queue[N
* N],start,end,last;

void  depth( int  x, int  y)
{
    
if(map[x][y]==1)
    
{
        s
++;
        x
=last.x;
        x
=last.y;
        
return;
    }

    last.x
=x;
    last.y
=y;
    
if(x==1&&y==1)
        
return;
    
if(map[x-1][y]==map[x][y]-1)
        depth(x
-1,y);
    
if(map[x+1][y]==map[x][y]-1)
        depth(x
+1,y);
    
if(map[x][y-1]==map[x][y]-1)
        depth(x,y
-1);
    
if(map[x][y+1]==map[x][y]-1)
        depth(x,y
+1);
}


int  main()
{
    
int front=0,rear=1;
    
int n,m,k,i,j;
    scanf(
"%d%d%d",&n,&m,&k);
    
for(i=0;i<=N;i++)
        
for(j=0;j<=N;j++)
            map[i][j]
=0;
    
while(k--)
    
{
        scanf(
"%d%d",&i,&j);
        map[i][j]
=-1;
    }

    scanf(
"%d%d",&start.x,&start.y);
    scanf(
"%d%d",&end.x,&end.y);
    queue[front].x
=start.x;
    queue[front].y
=start.y;
    map[start.x][start.y]
=1;
    
while(front<rear)
    
{
        i
=queue[front].x;
        j
=queue[front].y;
        
if(i==end.x&&j==end.y)
            
break;
        
if(i-1>0&&map[i-1][j]==0)
        
{
            map[i
-1][j]=map[i][j]+1;
            queue[rear].x
=i-1;
            queue[rear].y
=j;
            rear
++;
        }

        
if(j-1>0&&map[i][j-1]==0)
        
{
            map[i][j
-1]=map[i][j]+1;
            queue[rear].x
=i;
            queue[rear].y
=j-1;
            rear
++;
        }

        
if(i+1<=n&&map[i+1][j]==0)
        
{
            map[i
+1][j]=map[i][j]+1;
            queue[rear].x
=i+1;
            queue[rear].y
=j;
            rear
++;
        }

        
if(j+1<=m&&map[i][j+1]==0)
        
{
            map[i][j
+1]=map[i][j]+1;
            queue[rear].x
=i;
            queue[rear].y
=j+1;
            rear
++;
        }

        front
++;
    }

    
if(front==rear)
        printf(
"No Solution!/n");
    
else
    
{
        s
=0;
        last.x
=i;
        last.y
=j;
        printf(
"%d/n",map[i][j]-1);
        depth(i,j);
        printf(
"%d/n",s);
    }

    
return 0;
}

 YOYO's Note:
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄它是华丽的分隔线

【题意简述】

走迷宫,求从起点到终点之间走最短路径的可能方案数。


【粗略分析】

广度优先搜索求出最短路径,
然后用回溯从终点走回去,只有四周的点回合数为当前点回合数-1时方为可能路径,
最后返回路径为1时说明一条路径已完成,计数并返回,走下一条路径……

【C源代码】

#include < stdio.h >
#define  N 60
int  s,map[N + 1 ][N + 1 ];
typedef 
struct {
    
int x,y;
}
xy;
xy queue[N
* N],start,end,last;

void  depth( int  x, int  y)
{
    
if(map[x][y]==1)
    
{
        s
++;
        x
=last.x;
        x
=last.y;
        
return;
    }

    last.x
=x;
    last.y
=y;
    
if(x==1&&y==1)
        
return;
    
if(map[x-1][y]==map[x][y]-1)
        depth(x
-1,y);
    
if(map[x+1][y]==map[x][y]-1)
        depth(x
+1,y);
    
if(map[x][y-1]==map[x][y]-1)
        depth(x,y
-1);
    
if(map[x][y+1]==map[x][y]-1)
        depth(x,y
+1);
}


int  main()
{
    
int front=0,rear=1;
    
int n,m,k,i,j;
    scanf(
"%d%d%d",&n,&m,&k);
    
for(i=0;i<=N;i++)
        
for(j=0;j<=N;j++)
            map[i][j]
=0;
    
while(k--)
    
{
        scanf(
"%d%d",&i,&j);
        map[i][j]
=-1;
    }

    scanf(
"%d%d",&start.x,&start.y);
    scanf(
"%d%d",&end.x,&end.y);
    queue[front].x
=start.x;
    queue[front].y
=start.y;
    map[start.x][start.y]
=1;
    
while(front<rear)
    
{
        i
=queue[front].x;
        j
=queue[front].y;
        
if(i==end.x&&j==end.y)
            
break;
        
if(i-1>0&&map[i-1][j]==0)
        
{
            map[i
-1][j]=map[i][j]+1;
            queue[rear].x
=i-1;
            queue[rear].y
=j;
            rear
++;
        }

        
if(j-1>0&&map[i][j-1]==0)
        
{
            map[i][j
-1]=map[i][j]+1;
            queue[rear].x
=i;
            queue[rear].y
=j-1;
            rear
++;
        }

        
if(i+1<=n&&map[i+1][j]==0)
        
{
            map[i
+1][j]=map[i][j]+1;
            queue[rear].x
=i+1;
            queue[rear].y
=j;
            rear
++;
        }

        
if(j+1<=m&&map[i][j+1]==0)
        
{
            map[i][j
+1]=map[i][j]+1;
            queue[rear].x
=i;
            queue[rear].y
=j+1;
            rear
++;
        }

        front
++;
    }

    
if(front==rear)
        printf(
"No Solution!/n");
    
else
    
{
        s
=0;
        last.x
=i;
        last.y
=j;
        printf(
"%d/n",map[i][j]-1);
        depth(i,j);
        printf(
"%d/n",s);
    }

    
return 0;
}

【注意事项】

※ 初始化
※ 数组不要越界,行<n && 列<m


【点评】

刚翻了下那本算法书,发现回溯习题里有一题《罗密欧与茱丽叶》的图居然一样也……  = = 请54我……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值