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
#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源代码】
#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我……