人工智能之地形导航系统
项目需求
2018 年 11 月 26 日,“洞察”号火星探测器在火星上成功着陆,执行人类首次探究火星“内 心深处”的任务。火星上地形比较复杂,高低起伏,有山峰和低谷,稍有不慎,就会引起“翻 车”。因此我们必须要识别地形上的各个最高点(峰点)和最低点(谷点),以便为探测器 提供导航数据。
峰点就是一个其周围所有点的海拔都低于它的点
203 | 109 | 181 |
289 | 300 | 264 |
190 | 250 | 188 |
现在我们要做的就是分析来自地图上的海拔数据,以确定地形中峰点的数目和位置
二维数组
数组,就是多个同类型的元素的有序“组合”。如下的一组女兵,注:同类型是指都是女兵,不能混入男兵 -:)
二维数组,就是指含有多个数组的数组!
如果把一维数组理解为一行数据,那么,二维数组可形象地表示为行列结构。
二维数组的定义
和数组一样,需要先定义,再使用。
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};
a[0][0] 1 | a[0][1] 2 | a[0][2] 3 | a[0][3] 4 |
a[1][0] 5 | a[1][1] 6 | a[1][2] 7 | a[1][3] 8 |
a[2][0] 9 | a[2][1] 10 | a[2][2] 11 | a[2][3] 12 |
如下图表示,左侧表示的是一个大小为M+1的一维数组,右侧表示的是一个大小为(M+1)*(N+1)的二维数组。
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"); } | 11 |
二维数组的存储方式
设置断点调试,可以看到二位数组中的所有元素在内存中的存储方式
多维数组
上面讨论的二维数组的相关内容都适用于三维数组或更多维的数组。声明一个三维数组: 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 的网格, 加了下划线的网格即为峰点。
5039 5127 5238 5259 5248 5310 5299
5150 5392 5410 5401 5320 5820 5321
5290 5560 5490 5421 5530 5831 5210
5110 5429 5430 5411 5459 5630 5319
4920 5129 4921 5821 4722 4921 5129
5023 5129 4822 4872 4794 4862 4245
为了描述峰点的位置,我们需要使用一个位置方案:使用二维数组描述
假定左上角是[0][0],那么向下移动,则行号加 1;向右移动,则列号加 1, 那么这些峰点的位置就可以描述为:[2][1] [2][5] [4][3]。
位置确定后,与周围 4 个邻节点比较即可确定峰点!(注:网格边界点缺乏 4 个相邻点不计算峰点)地形数据保存于文件中。
算法设计
- 将地形数据从文件读入二维数组;
- 逐行遍历二维数组的每个元素,确定是否峰值并打印结果。
#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;
}
posted on 2022-10-29 14:37 会飞的鱼-blog 阅读(41) 评论(0) 编辑 收藏 举报 来源
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现