最少转弯问题

简介: 问题描述给出一张地图,这张地图被分为n×m(n,m

问题描述

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

输入

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

 

相关文章
|
7月前
|
存储 C++ 容器
c++vector容器-赋直操作讲解
c++vector容器-赋直操作讲解
678 0
|
7月前
|
JavaScript 前端开发
vue element plus Switch 开关
vue element plus Switch 开关
229 0
|
Linux 网络安全
Linux 服务器的21/22端口被禁止,如何解决?
22端口作为远程登录服务器的知名端口,如果22端口暴露在互联网必然会引起攻击。
873 0
|
Shell Linux Ubuntu
解决在SecurecCRT登录后,发现方向键、backspace(退格键)、delete(删除键)为乱码的问题
问题:使用securecrt ssh到linux之后,backspace(退格键),delete(删除键),以及4个方向键都为乱码,不能正常使用。按tab键也没有自动补全文件名。 即: 按Backspace(退格键)和delete(删除键)屏幕显示的是:^H 按方向键则屏幕显示的是:^[[A^[[B^[[C^[[D 环境: SecureCRT8.
3813 0
|
6月前
|
SQL 存储 大数据
揭秘数据库:核心技术、应用与实践
一、引言 数据库是现代信息技术的核心组成部分,它存储和管理着企业、组织乃至个人的重要数据
|
6月前
|
存储 关系型数据库 MySQL
MySQL基础指南:从入门到精通
MySQL基础指南:从入门到精通
175 0
|
7月前
|
应用服务中间件 nginx Docker
使用Docker构建本地Nginx容器及配置
使用Docker构建本地Nginx容器及配置
131 2
|
7月前
|
NoSQL 开发工具 数据库
基于Python开发的学生信息管理系统控制台程序(源码+可执行程序exe文件+程序配置说明书+程序使用说明书)
基于Python开发的学生信息管理系统控制台程序(源码+可执行程序exe文件+程序配置说明书+程序使用说明书)
102 0
|
7月前
|
SQL 分布式计算 Apache
流数据湖平台Apache Paimon(六)集成Spark之DML插入数据
流数据湖平台Apache Paimon(六)集成Spark之DML插入数据
226 0
|
运维 资源调度 Kubernetes
没有银弹,只有取舍 - Serverless Kubernetes 的思考与征程(一)
本文试着梳理 Kubernetes 所遇到的挑战,设计 Serverless Kubernetes的原因、挑战和发展路径。
1685 0
没有银弹,只有取舍 - Serverless Kubernetes 的思考与征程(一)