最少转弯问题

朴灿烈づ我的快乐病毒、 2022-02-04 14:57 359阅读 0赞

问题描述

给出一张地图,这张地图被分为n×m(n,m<=100)个方块,任何一个方块不是平地就是高山。平地可以通过,高山则不能。现在你处在地图的(x1,y1)这块平地,问:你至少需要拐几个弯才能到达目的地(x2,y2)?你只能沿着水平和垂直方向的平地上行进,拐弯次数就等于行进方向的改变(从水平到垂直或从垂直到水平)的次数。例如:如图,最少的拐弯次数为5。

img_747fbde98294a8f78dd6d7bfe3cb8b87.jpg

输入

  第一行:n和m。
  第二至n+1行:一个矩阵,为地图。(0:空地;1:高山。)
  第n+2行:x1,y1,x2和y2。

输出

  只有一行,为最少的转弯次数。

Sample input

5 7
1 0 0 0 0 1 0
0 0 1 0 1 0 0
0 0 0 0 1 0 1
0 1 1 0 0 0 0
0 0 0 0 1 1 0
1 3 1 7

Sample output

5

算法分析:

参考:

http://blog.csdn.net/qq\_30720681/article/details/50865093

http://blog.csdn.net/imaxtime/article/details/53038473

广搜,从出发点开始广搜。出发点入队,然后开始循环广搜。

每一次取出队头元素,从队头元素沿着四个方向中的一个方向直线前进直到行不通再换下一个方向。(注意,换方向后,队头尚未出队,还是从原先的队头出发,从下一个方向直线前进。)

每一轮直线前进过程中遇到的那些点的转弯次数都是当前队头元素的转弯次数(假如遇到了目的地,那就输出当前队头元素的转弯次数。)但是假如没有遇到目的地,当前遍历的点存储的转弯次数应该是“扫描到该点的队头的转弯次数再加1”。

说这么多,不如直接看代码:

  1. 1 #include<cstdio>
  2. 2 #include<cstring>
  3. 3 #include<queue>
  4. 4 using namespace std;
  5. 5
  6. 6 const int dx[]={
  7. 0,1,0,-1};//右下左上
  8. 7 const int dy[]={
  9. 1,0,-1,0};
  10. 8 struct point
  11. 9 {
  12. 10 int x,y,turn;
  13. 11 }_begin,_end,p;
  14. 12 queue<point> q;
  15. 13 int n,m,_map[101][101];
  16. 14 bool used[101][101];
  17. 15
  18. 16 int main()
  19. 17 {
  20. 18 memset(used,0,sizeof(used));
  21. 19
  22. 20 scanf("%d%d",&n,&m);
  23. 21 for(int i=1;i<=n;i++)
  24. 22 for(int j=1;j<=m;j++)
  25. 23 scanf("%d",&_map[i][j]);
  26. 24 scanf("%d%d%d%d",&_begin.x,&_begin.y,&_end.x,&_end.y);
  27. 25
  28. 26 q.push(_begin);
  29. 27 q.front().turn=0;
  30. 28 while(!q.empty())
  31. 29 {
  32. 30 for(int i=0;i<4;i++)
  33. 31 {
  34. 32 p.x=q.front().x+dx[i];
  35. 33 p.y=q.front().y+dy[i];
  36. 34 //从队头出发往dx[i]和dy[i]方向一直走,直到遇到边界或高山则停止,再从原队头换下一个方向走
  37. 35 while(p.x>0&&p.x<=n&&p.y>0&&p.y<=m&&!_map[p.x][p.y])
  38. 36 {
  39. 37 if(!used[p.x][p.y])
  40. 38 {
  41. 39 if(p.x==_end.x&&p.y==_end.y)
  42. 40 {
  43. 41 printf("%d\n",q.front().turn);//注意输出的是当前队头的转弯次数。
  44. 42 return 0;
  45. 43 }
  46. 44 used[p.x][p.y]=1;
  47. 45 p.turn=q.front().turn+1;
  48. 46 q.push(p);
  49. 47 }
  50. 48 p.x+=dx[i];
  51. 49 p.y+=dy[i];
  52. 50 }
  53. 51 }
  54. 52 q.pop();//当前队头元素已经不能再扩展,可以删除队头
  55. 53 }
  56. 54 }

假如还没明白,自行跟踪一下吧,下面是一个案例:

输入:

5 7
1 0 0 0 0 1 0
0 0 1 0 1 0 0
0 0 0 0 1 0 1
0 1 1 0 0 0 0
0 0 0 0 1 1 0
1 3 1 7

输出:

5

上面红色部分是路线。

可以换一个更简单的案例,比如把上面案例的目的点坐标改为(1,5)以及(3,4)。

发表评论

表情:
评论列表 (有 0 条评论,359人围观)

还没有评论,来说两句吧...

相关阅读

    相关 leetcoe253 最少会议室问题

    题目:有一堆会议,每个会议都有开始时间和结束时间,问至少需要几个房间可以安排下这些会议? 该问题可以使用贪心来做,使用小顶堆来实现最简单。 首先用一个最小堆来将会议按照会

    相关 问题 : 最少钱币数

    题目描述 这是一个古老而又经典的问题。用给定的几种钱币凑成某个钱数,一般而言有多种方式。例如:给定了 6 种钱币面值为 2、5、10、20、50、100,用来凑 15 元,