2019第十届蓝桥杯B组C++省赛E题 迷宫

题目链接 https://www.lanqiao.cn/problems/602/learning/

bfs最短路径输出表示

此题有五种方法orz...(唉。。。。。。。。。。。),总结在这里。这里用的第一种方法(见下面的思路)。


 

先说一下我错误的思路:先正着从起点开始搜一遍,求出每个点到起点的最短距离,再正着搜一遍,从起点往终点走,找比上一个大1的点,找到后记录路径,最后输出路径。

是这样的,这样是错误的,至于他为什么错,很难过,搞了两天也没搞懂。(下面有说)


 

接下来说一下正确的思路:先倒着从终点开始搜一遍,求出每个点到终点的最短距离,再正着搜一遍,从起点往终点走,找比上一个小1的点,找到后记录路径,最后输出路径。


 

为什么第一遍不能正着搜?有个dalao的解释是这样的:

回溯的时候有这种请况在dis[x][y]=147的时候下一步有两个点可以走都是最短的。因为迷宫里最短路径并非唯一,BFS可以求的最短路径没错,但得到的与题目要求的字典序最小可能不一样。有人说,按DLRU顺序走就可以了,但是,是开始标记dis数组时按着这顺序,还是回溯时按这个顺序呢?
答案是如果开始标记dis数组时是倒着搜时,然后回溯时按这个顺序是对的,但如果开始时正着搜的,那么回溯时就不能按这个顺序了,因为这样得到的路径是从(29,49)到(0,0)字典序最小的最短路径而不是从(0,0)到(29,49)字典序最小的最短路径。(原文链接https://blog.csdn.net/qq_40691051/article/details/102467168)。

好吧......我不能理解为什么变成是“从(29,49)到(0,0)字典序最小的最短路径”.....


 

放一个倒搜的模仿的dalao的半懂不懂的代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 char a[40][60];//存图 
 4 int dis[40][60];//存放各点到终点的距离,亦有类似于标记的作用 
 5 int dx[4]={1,0,0,-1};//字典序直接把方向数组处理好
 6 int dy[4]={0,-1,1,0};
 7 char ch[4]={'D','L','R','U'};
 8 string st;//存答案
 9 struct node    
10 {
11     int x;
12     int y;
13 };
14 bool check(int x, int y)
15 {
16     return x>0&&y>0&&x<=30&&y<=50&&a[x][y]=='0'&&dis[x][y]==-1;
17 }
18 void bfs(int bx,int by)
19 {//第一遍搜索求出各点到终点的最短距离
20     memset(dis,-1,sizeof(dis));
21     queue<node>q;
22     node start,next;
23     start.x=bx;
24     start.y=by;
25     q.push(start);
26     dis[30][50]=0;
27     while(!q.empty())
28     {
29         start=q.front(); 
30         q.pop();
31         for(register int i=0;i<4;i++)
32         {
33             next.x=start.x+dx[i];
34               next.y=start.y+dy[i];
35               if(check(next.x,next.y))
36             {
37                 dis[next.x][next.y]=dis[start.x][start.y]+1;
38                   q.push(next);    
39               }
40         }
41       }
42 }
43 int main()
44 {
45     for(int i=1;i<=30;i++)
46         for(int j=1;j<=50;j++)
47               cin>>a[i][j];
48      bfs(30,50); 
49       int x=1,y=1;//从起点开始遍历 
50       while(x!=30||y!=50) 
51       {
52           for(int i=0;i<4;i++)
53         {
54             int newx=x+dx[i];
55                int newy=y+dy[i];
56                if(newx>0&&newx<=30&&newy>0&&newy<=50&&a[newx][newy]=='0'&&dis[newx][newy]==dis[x][y]-1)
57             {
58                 x=newx;    y=newy;
59                 st+=ch[i];
60                 break;
61             }
62           }
63       }    
64     cout<<st<<endl;
65     return 0;
66 }

 

这是我错误思路的代码:(不重要!划掉!)

(第26、48、56行不同)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 char a[40][60];//存图
 4 int dis[40][60];//存放各点到终点的距离,亦有类似于标记的作用
 5 int dx[4]={-1,0,0,1};//字典序直接把方向数组处理好
 6 int dy[4]={0,1,-1,0};
 7 char ch[4]={'D','L','R','U'};
 8 string st;//存答案
 9 struct node
10 {
11     int x;
12     int y;
13 };
14 bool check(int x, int y)
15 {
16     return x>0&&y>0&&x<=30&&y<=50&&a[x][y]=='0'&&dis[x][y]==-1;
17 }
18 void bfs(int bx,int by)
19 {//第一遍搜索求出各点到终点的最短距离
20     memset(dis,-1,sizeof(dis));
21     queue<node>q;
22     node start,next;
23     start.x=bx;
24     start.y=by;
25     q.push(start);
26     dis[1][1]=0;
27     while(!q.empty())
28     {
29         start=q.front();
30         q.pop();
31         for(register int i=0;i<4;i++)
32         {
33             next.x=start.x+dx[i];
34               next.y=start.y+dy[i];
35               if(check(next.x,next.y))
36             {
37                 dis[next.x][next.y]=dis[start.x][start.y]+1;
38                   q.push(next);
39               }
40         }
41       }
42 }
43 int main()
44 {
45     for(int i=1;i<=30;i++)
46         for(int j=1;j<=50;j++)
47               cin>>a[i][j];
48      bfs(1,1);
49       int x=1,y=1;//从起点开始遍历
50       while(x!=30||y!=50)
51       {
52           for(int i=0;i<4;i++)
53         {
54             int newx=x+dx[i];
55                int newy=y+dy[i];
56                if(newx>0&&newx<=30&&newy>0&&newy<=50&&a[newx][newy]=='0'&&dis[newx][newy]==dis[x][y]+1)
57             {
58                 x=newx;    y=newy;
59                 st+=ch[i];
60                 break;
61             }
62           }
63       }
64     cout<<st<<endl;
65     return 0;
66

好心累,dalao的讲解看不懂,lqs和cjh讲的也不理解。。。。。。5555555,等问过老师再来更新吧。

 

posted @ 2022-04-02 20:31  爱吃虾滑  阅读(72)  评论(0编辑  收藏  举报