人工智能之地形导航系统

简介: 人工智能之地形导航系统

项目需求

2018 年 11 月 26 日,“洞察”号火星探测器在火星上成功着陆,执行人类首次探究火星“内 心深处”的任务。火星上地形比较复杂,高低起伏,有山峰和低谷,稍有不慎,就会引起“翻 车”。因此我们必须要识别地形上的各个最高点(峰点)和最低点(谷点),以便为探测器 提供导航数据。


image.png峰点就是一个其周围所有点的海拔都低于它的点

1.PNG


现在我们要做的就是分析来自地图上的海拔数据,以确定地形中峰点的数目和位置

二维数组

数组,就是多个同类型的元素的有序“组合”。如下的一组女兵,注:同类型是指都是女兵,不能混入男兵 -:)


二维数组,就是指含有多个数组的数组!

如果把一维数组理解为一行数据,那么,二维数组可形象地表示为行列结构。

二维数组的定义

和数组一样,需要先定义,再使用。

int a[25] ; //一行女兵实例:

int      a[5][25];     //五行女兵

//定义了一个二维数组,

//数组名是“a”,

//包含 5 行 25 列,共 125 元素,

//每个元素是 int 类型的变量

二维数组的初始化


int a[3][4];  //二维数组元素的值可能是随机的(全局变量会初始化为 0,局部变量值随机)


方式一 初始化时指定每行的值


int a[3][4]={    //等效于 int a[][4]


{1,     2,     3,     4},


{5,     6,     7,     8},


{9,    10,    11,   12}


};


注:最外围括号内部的每个括号相当于初始化一行,括号中可以省略某些元素的初始化


方式二初始化时从头开始,依次序进行


int a[3][4]={ 1,2,3,4,5,6,7,8,9,10,11,12};


int a[3][4]={ 0}; //所有元素都初始化为 0


注:后面的多个元素可以不指定,不指定全部初始化为 0

#include <stdlib.h> #include <stdio.h>
int main(void){
//int ages[5][25];//定义一个二维数组 int i=0, j=0;
//初始化
//第一种方式 初始化时指定每行的值
int a[3][4]={
{1},//省略掉得列会默认置零
{5,6,7},
{9,10,11,12}
};
//第二种方式 初始化时从头开始,依次序进行
int a1[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int a2[3][4]={1};//只初始化第一个,其他得默认置零
for(i=0; i<3; i++){ for(j=0; j<4; j++){ printf("%d ", a[i][j]);
}
printf("\n");
}
system("pause");
return 0;
}

二维数组的访问

a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};


2.PNG

如下图表示,左侧表示的是一个大小为M+1的一维数组,右侧表示的是一个大小为(M+1)*(N+1)的二维数组。

8d01823dd8094831becccc16239fc2c2.png



int i=0, j=0; int a[3][4];
//给数组成员赋值
for(int i=0;i<12; i++){ a[i/4][i%4] = i+1;
}
//或
for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ a[i][j] = 4*i+j+1;
}
}
//输出
for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ printf("%d ",a[i][j]);
} printf("\n");
}

二维数组的存储方式

设置断点调试,可以看到二位数组中的所有元素在内存中的存储方式

aaedec8366bd4899a0058da03c9d72f9.png




307acf9ff9924b3f94d83e7da78af553.png


多维数组


上面讨论的二维数组的相关内容都适用于三维数组或更多维的数组。声明一个三维数组: int girl[3][8][5];


可以把一维数组想象成一排女兵,把二维数组想象成一个女兵方阵,把三维数组想象成多个女兵方阵。这样,当你要找其中的一个女兵时,你只要知道她在哪个方阵(从 0、1、2 中选择),在哪一行(从 0-7)中选择,在哪一列(从 0-4 中选择)


二维数组作为函数的参数

切记!数组作为函数的参数传递,不是单纯的值传递,传递的是数组本身。

二维数组作为函数的参数:

#include <stdio.h>
#include <stdlib.h>
//版本1 指明参数
void print1(int a[3][4]){ for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ printf("%d ",a[i][j]);
}
printf("\n");
}
}
//版本1 省略一个高维参数
void print2(int a[][4], int lines){ for(int i=0;i<lines; i++){ for(int j=0;j<4; j++){ printf("%d ",a[i][j]);
}
printf("\n");
}
}
int main(void){
//int arr[3][4]={{},{3,4}}; int a[3][4]={0}; int i=0; int j=0;
//给数组成员赋值
for(int i=0;i<3; i++){ for(int j=0;j<4; j++){ a[i][j] = 4*i+j;
}
}
print1(a);
print2(a);
}

常见错误总结

数组定义时编译器不能确定数组的大小

int a[3][] ; int a[][4] ;


int a[3][]={{1,2},{3,4},{5,6}}


一条原则:仅定义时(无初始化)不能省略,有初始化可以省略高维


严禁数组越界


在使用数组时,要防止数组下标超出边界。也就是说,必须确保下标是有效的值。


int a[10] ;         a[10]=100;    //错误,访问越界,a[10] 的成员是 a[0] - a[9]


int a[3][4];      a[3][0]=666; //错误, a[3][4] 包含了 3 行 4 列的数组,行下标也是从 0 开始,有效范围 0 - 2


数组(无论几维)传参并不是整个数组的复制

#include <stdio.h>
#include <stdlib.h> //int arr[3][4];
void fun(int a[3][4]){
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){ a[i][j]=0;
}
}
}
int main(void){
//int arr[3][4]={{},{3,4}};
int a[3][4]={0};
int i=0; int j=0;
//给数组成员赋值
for(int i=0;i<3; i++){
for(int j=0;j<4; j++){
a[i][j] = 4*i+j;
}
}
fun(a);
//输出
for(int i=0;i<3; i++){
for(int j=0;j<4; j++){
printf("%d ",a[i][j]);
}
printf("\n");
}

项目实现

假设下面的数据代表一个 6 x 7 的网格, 加了下划线的网格即为峰点。3.PNG

为了描述峰点的位置,我们需要使用一个位置方案:使用二维数组描述

假定左上角是[0][0],那么向下移动,则行号加 1;向右移动,则列号加 1, 那么这些峰点的位置就可以描述为:[2][1]   [2][5]    [4][3]


位置确定后,与周围 4 个邻节点比较即可确定峰点!(注:网格边界点缺乏 4 个相邻点不计算峰点)地形数据保存于文件中。


49997b3f13ba49edb4ac1b2ea55c3709.png


算法设计

  1. 将地形数据从文件读入二维数组;
  2. 逐行遍历二维数组的每个元素,确定是否峰值并打印结果。
#include <iostream>
#include <string>
#include <fstream>
#include <Windows.h>
using namespace std;
#define N 64
bool isPeak(int map[N][N], int nrows, int ncols)
{
  if ((map[nrows][ncols] > map[nrows + 1][ncols]) &&
    (map[nrows][ncols] > map[nrows - 1][ncols]) &&
    (map[nrows][ncols] > map[nrows][ncols + 1]) &&
    (map[nrows][ncols] > map[nrows][ncols] - 1))
  {
    return true;
  }
  else
  {
    return false;
  }
}
int main(void)
{
  string filename;
  fstream file;
  int map[N][N];
  int ncols, nrows;
  cout << "请输入你要打开的文件:";
  cin >> filename;
  file.open(filename.c_str());
  if (file.fail())
  {
    cerr << "打开文件失败" << endl;
    exit(1);
  }
  file >> nrows >> ncols;
  if (nrows > N || ncols > N)
  {
    cerr << "行或列超出指定范围" << endl;
    exit(1);
  }
  for (int i = 0; i < nrows; i++)
  {
    for (int j = 0; j < ncols; j++)
    {
      file >> map[i][j];
    }
  }
  for (int i = 1; i < nrows-1; i++)
  {
    for (int j = 1; j < ncols-1; j++)
    {
      if (isPeak(map, i, j))
      {
        cout << "行:" << i << "列" << j << "峰值" << map[i][j] << endl;
      }
    }
  }
  file.close();
  system("pause");
  return 0;
}


相关文章
|
27天前
|
安全 人工智能 机器学习/深度学习
人工智能技术在飞机飞行领域的应用
人工智能技术在飞机飞行领域的应用
11 0
|
9月前
|
自动驾驶
【无人车】无人驾驶地面车辆避障研究(Matlab代码实现)
【无人车】无人驾驶地面车辆避障研究(Matlab代码实现)
|
10月前
|
机器学习/深度学习 人工智能 算法
当医学插上人工智能的翅膀
当医学插上人工智能的翅膀
|
机器学习/深度学习 人工智能 自动驾驶
自动驾驶为什么需要“新物种”?
自动驾驶为什么需要“新物种”?
103 0
|
人工智能 监控 安全
人工智能摄像机的未来
人工智能摄像机具有许多功能,可以增强现代生活的许多方面。未来的智慧城市将依靠诸如此类的技术来增加安全操作、加快访问控制、改善交通流量等等。
184 0
人工智能摄像机的未来
|
开发框架 人工智能 算法
游戏人工智能——聚集与避障
智能体只考虑哪些在检测盒内的障碍物。 1.初始的时候,要将游戏世界中所有的障碍物都迭代到内存中,并标记哪些在检测盒内的障碍物以作进一步分析,然后把所有已经标记的障碍物都转换到智能体的局部空间。 2.转换坐标后,那些x坐标为负值的物体将不被考虑,所以问题就变得简单多了,接下来必须要检测障碍物是否和检测盒重叠。使障碍物的包围半径扩大检测盒宽度的一半。然后测试该障碍物的y值是否小于这个值(即障碍物的包围半径加上检测盒宽度的一半)。 此时,只剩下那些与检测盒相交的障碍物了。 3.接下来我们找出离智能体最近的相交点。 再一次在局部空间中计算,第三步中扩大了障碍物的包围半径。 用简单的线圆周相交测试
217 0
游戏人工智能——聚集与避障
|
传感器 编解码 监控
机器人与触觉传感技术的碰撞,一文初探人类与机器人的触觉传感
本文对人类和机器人的触觉传感知识进行了简单的梳理和探讨,并以此为基础给出了两篇论文中的应用实例。
284 0
机器人与触觉传感技术的碰撞,一文初探人类与机器人的触觉传感
|
机器学习/深度学习 监控 自动驾驶
伸手挡汽车!机器学习教自动驾驶汽车看懂行人手势
伸手挡汽车!机器学习教自动驾驶汽车看懂行人手势
伸手挡汽车!机器学习教自动驾驶汽车看懂行人手势
|
传感器 安全
用蚕丝和钻石,科学家制作出了新型生物传感器
医学再一次惊艳到了我们:当蚕丝这种古老的纤维和纳米钻石搭配使用时,原来会在科学界有这么大的突破。
|
机器学习/深度学习 传感器 算法
卫星联手机器学习,如何检测海洋中的塑料垃圾?
塑料制品往往色彩多样,不同尺寸,不同类型,大多数由多种化学物质制成,更糟糕的是,地球上的海洋区域广阔无垠,每年新增的数百万吨塑料很快就会四散蔓延,这种“大塑料”会逐渐分解成细小的塑料块,难以循迹,给海洋生物造成致命威胁。