这道题其实想法上没有什么思维局限,但是在dfs上有一个时限问题,所以需要在dfs函数中进行一定的剪枝,并且在输入上要进行循环字符输入,当然,按字典序的话,直接在刚开始就按字典序来遍历
//dfs代码如下
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
char map[50][100];
int book[50][100];
int mins[50][100];//此时的mins数组是记录在这一点时的最小步数是多少
char road[1000];
char road1[1000];
int dx[4]={1,0,0,-1};
int dy[4]={0,-1,1,0};
char dir[4]={'D','L','R','U'};
int min=1000;
void dfs(int x,int y,int step)
{
int i,j,kx,ky;
if(x==29&&y==49){
if(step<min){
min=step;
for(i=0;i<min;i++){
road1[i]=road[i];
//printf("%c ",road1[i]);
}
}
return;
}
for(i=0;i<4;i++){
kx=x+dx[i];
ky=y+dy[i];
if(kx>=0&&kx<=29&&ky>=0&&ky<=49&&map[kx][ky]==0&&book[kx][ky]==0&&step+1<mins[kx][ky]){//step+1<mins 是判断如果此时到达这一步时没有原先走过这一步时步数少,这一步就不走了,类似一种剪枝
book[kx][ky]=1;
mins[kx][ky]=step+1;
road[step]=dir[i];
dfs(kx,ky,step+1);
book[kx][ky]=0;
}
}
return;
}
int main(){
int n,i,j;
char a;
for(i=0;i<30;i++){
for(j=0;j<50;j++){
scanf("%c",&a);
map[i][j]=a-'0';
mins[i][j]=10000;//使每一点的初始步数都为一个极大值,这样方便以后对这个点更新
book[i][j]=0;
}
getchar();
}
book[0][0]=1;
dfs(0,0,0);
//printf("%d\n",min);
for(i=0;i<min;i++){
printf("%c",road1[i]);
}
printf("\n");
return 0;
}
可以看到除了一些dfs常规的代码,还包括一个对到达每个点时的步数进行一个统计和更新,用到了数组mins,并在刚开始时对mins进行极大值初始化,当然也可以用memset(mins,1,sizeof)这种形式进行初始化,但要记得头文件
初始化过后就是对mins的一个运用,放在dfs里进行一个判断和剪枝,当到达这一点的步数比原先这一点已有的步数小时,举个例子:
如果原先在(2,3)这个点的mins=6,此时又进行了一遍路径探索,探索到 了(2,3)这一点,但是此时的step为5,说明新的这一路径的步数到达这一点时更小,满足题目的要求,就继续这一路径的探索,并更新mins为5,反之,如果step>6,则经过(2,3)这一路径的探索就可以不用再继续了,因为再往后就是赘余,在此点已经>6了,那继续到下一个点则步数会更大,mins依然为6,无需更新
上述就是防止一个点被多次无用访问
其实这个代码在刚开始时卡在了输入map的问题上,我运用%s进行30行字符串的输入,但是整个代码一进dfs就无限循环再也出不来,所以在参考了下面博客后写出的代码,但是这位大佬好像并没有解释的很清,还有错别字(小声bb),所以我就来解释一下这个mins数组,害
https://blog.csdn.net/weixin_45483201/article/details/104148397
个人认为bfs可能是这道题更好的选择,因为bfs在遇到最小时就可快速弹出,并将路径打印出来,比dfs要快那么一些些,代码复杂度也小一些
//bfs代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
typedef struct point{
int x;
int y;
int step;//储存此时的步数
int father; //储存路径
char dir1;//储存此时此刻方向
}point;
char map[50][100];
int book[50][100];
char road[1000];
int dx[4]={1,0,0,-1};
int dy[4]={0,-1,1,0};
char dir[4]={'D','L','R','U'};
//int min=1000;
int tx,ty;
int main(){
int n,i,j,k;
char a;
int flag=0;
int head=0;
int tail=0;
point queue[10000];
for(i=0;i<30;i++){
for(j=0;j<50;j++){
scanf("%c",&a);
map[i][j]=a-'0';
book[i][j]=0;
}
getchar();
}
queue[head].x=0;
queue[head].y=0;
queue[head].step=0;
queue[head].father=-1;
book[0][0]=1;
tail++;
while(head!=tail){
for(i=0;i<4;i++){
tx=queue[head].x+dx[i];
ty=queue[head].y+dy[i];
if(tx>=0&&tx<=29&&ty>=0&&ty<=49&&map[tx][ty]==0&&book[tx][ty]==0){
queue[tail].x=tx;queue[tail].y=ty;
queue[tail].step=queue[head].step+1;
queue[tail].father=head;
queue[tail].dir1=dir[i];
tail++;
book[tx][ty]=1;
}
if(tx==29&&ty==49){
flag=1;
break;
}
}
if(flag==1) break;
head++;
}
k=tail-1;
i=queue[k].step;
j=queue[k].step;
while(k!=-1){//将倒序路径放入数组
road[i]=queue[k].dir1;
i--;//i最小减到1,减不到0,因为k=-1时就break
k=queue[k].father;
}
for(i=1;i<=j;i++){
printf("%c",road[i]);
}
printf("\n");
return 0;
}
相比较而言bfs在寻找的时候比较好想,也比较好实现,但是输出路径的时候真的很麻烦,要有father,针对此题还要有每一步的direction,反正这道题总体来说想法简单,实现起来有些麻烦,容易绕晕。