给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?
第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x 1, y 1, x 2, y 2 (1 ≤ k ≤ 10, 1 ≤ x 1, x 2 ≤ n, 1 ≤ y 1, y 2 ≤ m),其中k表示gloria最多能转的弯数,(x 1, y 1), (x 2, y 2)表示两个位置,其中x 1,x 2对应列,y 1, y 2对应行。
2 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 5 5 ...** *.**. ..... ..... *.... 2 1 1 1 3
noyes
刚开始我拿到这道题便看出来了这是一道很简(keng)单(die)的BFS的题目,这道题目的难点在于计算层数的时候不是以步数为单位的,是以转向的次数为单位。每转一次向,为1层,直到第二次转向才到下一层。所以转向后,一定要搜索到底!!!!!这才是关键。
下面放一下刚开始写的代码。
#include <iostream> #include<stdio.h> #include<math.h> #include<string.h> int dir[4][2]={0,1,1,0,0,-1,-1,0};//右、下、左、上 int k; int m,n; int x2,y2; int top=0,p=0; int w[101][101]; struct node { int d; int x,y;//x是行,Y是列 }; struct node zhan[10010]; void BFS(int xi,int yi) { if(xi==x2&&yi==y2) { printf("yes\n"); return ; } for(int i=0;i<4;i++) { int x0=zhan[top].x,y0=zhan[top].y; if(w[zhan[top].x+dir[i][0]][zhan[top].y+dir[i][1]]==0) { while(w[x0+dir[i][0]][y0+dir[i][1]]==0) { p++; x0=x0+dir[i][0]; y0=y0+dir[i][1]; zhan[p].x=x0; zhan[p].y=y0; zhan[p].d=zhan[top].d+1; w[x0][y0]=2; // printf(" (%d,%d) %d %d\n",x0,y0,zhan[top].d,zhan[p].d); if(zhan[p].d>k) { printf("no\n"); return ;} if(x0==x2&&y0==y2) { //printf("yes,%d\n",zhan[p].d); printf("yes\n"); return ; } } } } top++; BFS(zhan[top].x,zhan[top].y); } int main() { int a; scanf("%d",&a); while(a--) { top=0,p=0; memset(w,1,sizeof(w)); scanf("%d %d",&m,&n); int i,j; for(i=1;i<=m;i++) { getchar(); for(j=1;j<=n;j++) { char c; scanf("%c",&c); if(c=='.') w[i][j]=0; else w[i][j]=1; } } int x1,y1; scanf("%d %d %d %d %d",&k,&y1,&x1,&y2,&x2); if(x2>m||y2>n||x2<1||y2<1||w[x2][y2]==1) { printf("no\n"); return 0; } if(x1>m||y1>n||x1<1||y1<1||w[x1][y1]==1) { printf("no\n"); return 0; } zhan[0].x=x1; zhan[0].y=y1; zhan[0].d=-1; w[x1][y1]=2; BFS(x1,y1); } return 0; }
然后怎么提交都不对!!!为什么呢,因为忽略了一个很大的问题,就是中间BFS函数部分,输出yes的判断条件那里,因为他是按照转弯数搜索的,也就是说很可能有的点在这一层上但是是后来才转到这里的,是搜索完别的层数多的之后回溯会来的。所以中间会出现一段转弯数>要求的转弯数的情况,这时候这段代码会直接return出来,就没办法进行后面的搜索了。所以一直wrong answer。(其实这里我也有个小小的疑惑,为什么递归的时候退出来回到原来的函数就不行了呢)然后改进了一下,对了。并且把递归改成了循环。
/* 1 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 5 5 ...** *.**. ..... ..... *.... 2 1 1 5 3 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 */ #include <iostream> #include<stdio.h> #include<math.h> #include<string.h> int dir[4][2]={0,1,1,0,0,-1,-1,0};//右、下、左、上 int k; int m,n; int x2,y2; int v[101][101]; char w[101][101]; struct node { int d; int x,y;//x是行,Y是列 }; bool check(int x,int y) { if(x >= 1 && y >= 1 && x <= m && y <= n && w[x][y] != '*') return 1; return 0; } struct node zhan[10010]; void BFS(int xi,int yi) { int top=0,p=1; if(xi==x2&&yi==y2) { printf("yes\n"); return ; } zhan[0].x=xi; zhan[0].y=yi; zhan[0].d=-1; v[xi][yi]=1; while(top!=p) { //printf("%d %d (%d,%d)\n",top,p,zhan[p].x,zhan[p].y); for(int i=0;i<4;i++) { int x0=zhan[top].x+dir[i][0],y0=zhan[top].y+dir[i][1]; while( check(x0,y0) ) { if(v[x0][y0]==0) { zhan[p].x=x0; zhan[p].y=y0; zhan[p].d=zhan[top].d+1; v[x0][y0]=1; // printf("(%d,%d)\n",x0,y0); if(x0==x2&&y0==y2&&zhan[p].d<=k) { printf("yes\n"); return ; } p++; } x0=x0+dir[i][0]; y0=y0+dir[i][1]; } } top++; } printf("no\n"); return ; } int main() { int a; scanf("%d",&a); while(a--) { memset(v, 0, sizeof(v)); memset(w, 0, sizeof(w)); int top=0,p=0; memset(w,1,sizeof(w)); scanf("%d %d",&m,&n); int i,j; for(i=1;i<=m;i++) { for(j=1;j<=n;j++) { scanf(" %c",&w[i][j]); } } int x1,y1; scanf("%d %d %d %d %d",&k,&y1,&x1,&y2,&x2); BFS(x1,y1); } return 0; }