二维数组的定义与使用
二维数组的定义与使用
掌握 C++二维数组(不包括变长数组)的基本概念及使用。
二维数组可理解为「行 × 列」的表格。定义如 int a[2][3]; 表示 2 行 3 列,共 6 个 int,在内存中按行优先连续存放。元素用 a[i][j] 访问,下标从 0 开始。
GESP 四级常给部分初始化或循环遍历,考下标范围、某元素值、或 sizeof 计算总字节数。变长数组(VLA)不在大纲范围,见到 int n; cin>>n; int a[n]; 应知道这不属于标准 C++ 四级考点。
int grid[2][3] = {{1,2,3}, {4,5,6}};
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 3; ++j)
cout << grid[i][j] << ' ';
行、列下标不要写反;嵌套循环外层通常是行、内层是列,与题意一致即可。
假定整型是32位,对一个 2 行 3 列的二维整数数组 array,假设数组第一个元素在内存中的地址为 0x7ffee4065820,则第2行第2个元素的地址 &array[1][1] 为( )。
int array[2][3] = {
{0, 1, 2},
{3, 4, 5}
};
下面( )正确定义二维数组。
int arr[3][] 是一个正确的二维数组的声明。
假设 int arr[2][3] = {{1,2,3},{4,5,6}};,则 arr[1][2] 的值是( )。
下面( )正确定义了二维数组。
二维数组作为函数参数时,必须显式指定所有维度的大小。
荒地开垦
C++时间 1 s内存 512 MB标准输入输出
小杨有一大片荒地,可以表示为一个 n 行 m 列的网格图。
小杨想要开垦这块荒地,但荒地中一些位置存在杂物,对于一块不存在杂物的荒地,该荒地可以开垦当且仅当其上下左右四个方向相邻的格子均不存在杂物。
小杨可以选择至多一个位置,清除该位置的杂物,移除杂物后该位置变为荒地。小杨想知道在清除至多一个位置的杂物的情况下,最多能够开垦多少块荒地。
输入格式
第一行包含两个正整数 n,m,含义如题面所示。
之后 n 行,每行包含一个长度为 m 且仅包含字符 . 和 # 的字符串。如果为 .,代表该位置为荒地;如果为 #,代表该位置为杂物。
输出格式
输出一个整数,代表在清除至多一个位置的杂物的情况下,最多能够开垦的荒地块数。
样例
3 5 ..... .#..# .....
11
移除第二行从左数第二块空地的杂物后:
.....
....#
.....
第一行从左数前 4 块荒地,第二行从左数前 3 块荒地,第三行从左数前 4 块荒地,均可开垦,4+3+4=11。
数据范围
对于全部数据,有 1≤n,m≤1000。
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB
判题结果
二阶矩阵
C++时间 1 s内存 512 MB标准输入输出
小 A 有一个 n 行 m 列的矩阵 A。
小 A 认为一个 2×2 的矩阵 D 是好的,当且仅当 D1,1×D2,2=D1,2×D2,1。其中 Di,j 表示矩阵 D 的第 i 行第 j 列的元素。
小 A 想知道 A 中有多少个好的子矩阵。
输入格式
第一行,两个正整数 n,m。
接下来 n 行,每行 m 个整数 Ai,1,Ai,2,…,Ai,m。
输出格式
一行,一个整数,表示 A 中好的子矩阵的数量。
样例
3 4 1 2 1 0 2 4 2 1 0 3 3 0
2
样例中好的子矩阵如下:

数据范围
对于所有测试点,保证 1≤n≤500,1≤m≤500,−100≤Ai,j≤100
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB
判题结果
下面的函数接收一个 3 行 4 列的二维数组并输出其中元素,则横线上不能填写( )。
void printArray(________) {
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 4; ++j)
std::cout << arr[i][j] << " ";
}
在 C++ 中,int arr[3][4] 和 int* arr = new int[12] 均可模拟一个 3 行 4 列的二维数组。关于这两种方式,下面说法错误的是( )。
下面这段代码不合法,因为每一行都必须显式初始化 3 个元素。
int arr[2][3] = {{1, 2}, {3}};
画布裁剪
C++时间 1 s内存 512 MB标准输入输出
小 A 在高为 h 宽为 w 的矩形画布上绘制了一幅画。由于画布边缘留白太多,小 A 想适当地裁剪画布,只保留画的主体。具体来说,画布可以视为 h 行 w 列的字符矩阵,其中的字符均为 ASCII 码位于 33∼126 之间的可见字符,小 A 只保留画布中由第 x1 行到第 x2 行、第 y1 列到第 y2 列构成的子矩阵。
小 A 将画布交给了你,你能帮他完成画布的裁剪吗?
输入格式
第一行,两个正整数 h,w,分别表示画布的行数与列数。
第二行,四个正整数 x1,x2,y1,y2,表示保留的行列边界。
接下来 h 行,每行一个长度为 w 的字符串,表示画布内容。
输出格式
输出共 x2−x1+1 行,每行一个长度为 y2−y1+1 的字符串,表示裁剪后的画布。
样例
3 5 2 2 2 4 ..... .>_<. .....
>_<
5 5 1 2 3 4 AbCdE fGhIk LmNoP qRsTu VwXyZ
Cd hI
数据范围
对于所有测试点,保证 1≤h,w≤100,1≤x1≤x2≤h,1≤y1≤y2≤w。
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB
判题结果
给定如下定义的数组 arr,则 *(*(arr + 1) + 2) 的值是( )。
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
下面代码将二维数组 arr 传递给函数 f,函数内部用 arr[i][j] 访问元素,函数参数声明为 int arr[][4] 是错误的。
void f(int arr[][4], int rows) {
// 访问 arr[i][j]
}
int main() {
int arr[3][4] = { /* 初始化 */ };
f(arr, 3);
}
排兵布阵
C++时间 1 s内存 512 MB标准输入输出
作为将军,你自然需要合理地排兵布阵。地图可以视为 n 行 m 列的网格,适合排兵的网格以 1 标注,不适合排兵的网格以 0 标注。现在你需要在地图上选择一个矩形区域排兵,这个矩形区域内不能包含不适合排兵的网格。请问可选择的矩形区域最多能包含多少网格?
输入格式
第一行,两个正整数 n,m,分别表示地图网格的行数与列数。
接下来 n 行,每行 m 个整数 ai,1,ai,2,…,ai,m,表示各行中的网格是否适合排兵。
输出格式
一行,一个整数,表示适合排兵的矩形区域包含的最大网格数。
样例
4 3 0 1 1 1 0 1 0 1 1 1 1 1
4
3 5 1 0 1 0 1 0 1 0 1 0 0 1 1 1 0
3
数据范围
对于所有测试点,保证 1≤n,m≤12,0≤ai,j≤1。
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB
判题结果
小杨用一个二维数组表示棋盘,其中 1 表示有棋子,0 表示没有棋子。他想知道第 2 行 第 3 列有没有棋子,可采用的代码是:( )。
int a[3][4] = {
{1, 0, 1, 0},
{0, 1, 0, 1},
{1, 1, 0, 0}
};
执行完下面的代码后,*(p + 5) 和 arr[1][1] 的值分别是( )。
int arr[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
int* p = &arr[0][0];
在 C++ 中,定义如下二维数组:int a[3][4];,数组 a 在内存中是按行优先连续存放的,即 a[0][0]、a[0][1]、a[0][2]、a[0][3] 在内存中是连续的。
建造
C++时间 1 s内存 512 MB标准输入输出
小 A 有一张 M 行 N 列的地形图,其中第 i 行第 j 列的数字 aij 代表坐标 (i,j) 的海拔高度。
停机坪为一个 3×3 的区域,且内部所有 9 个点的最大高度和最小高度之差不超过 H。
小 A 想请你计算出,在所有适合建造停机坪的区域中,区域内部 9 个点海拔之和最大是多少。
输入格式
第一行三个正整数 M,N,H,含义如题面所示。
之后 M 行,第 i 行包含 N 个整数 ai1,ai2,…,aiN,代表坐标 (i,j) 的高度。
数据保证总存在一个适合建造停机坪的区域。
输出格式
输出一行,代表最大的海拔之和。
样例
5 5 3 5 5 5 5 5 5 1 5 1 5 5 5 5 5 5 5 2 5 2 5 3 5 5 5 2
40
数据范围
对于所有测试点,保证 1≤M,N≤103,1≤H,aij≤105。
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB
判题结果
已知:
int a[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
int (*p)[4] = a;
则表达式 *(*(p + 2) + 1) 的值为( )。
执行下面代码,输出结果为 5。
int main() {
int a[2][3];
cout << &a[1][2] - &a[0][1] << endl;
return 0;
}
山之谷
C++时间 1 s内存 512 MB标准输入输出
现有一片山地,可以视为一个 N 行 M 列的网格图,第 i 行 j 列的海拔为 hi,j。
如果一个单元格的海拔不高于其所有相邻单元格(相邻包括上、下、左、右、左上、右上、左下、右下,最多 8 个方向)的海拔,则称该单元格为山谷。
请你数一数该片山地中有多少山谷。
输入格式
第一行包含 2 个整数 N,M,表示山地的大小。
之后 N 行,每行包含 M 个整数 hi,1,hi,2,⋯,hi,M,表示海拔。
输出格式
输出 1 行,包含 1 个整数 C,表示山谷的数量。
样例
3 5 7 6 6 7 9 6 5 6 7 6 6 5 7 8 9
3
样例 1 如图所示,绿色单元格代表山谷:
:::align{center}

:::
数据范围
保证 1≤N,M≤100,1≤hi,j≤105。
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB
判题结果
小杨正在开发一款名为“星际网格”的游戏,他用二维数组 int map[5][4]; 来表示地图。已知 int 占 4 字节,如果 map 的内存地址是 0x2000,则表达式 &map + 1 的地址值是( )。
某班 3 个小组、每组 4 名同学的分数存入下面的二维数组 score,则 score[1][2] 的值是( )。
int score[3][4] = {
{80, 81, 82, 83},
{90, 91, 92, 93},
{70, 71, 72, 73}
};
在 C++ 中定义二维数组并初始化时,可以省略第一维,但不能省略第二维。因此 int a[][2] = {{1, 2}, {3, 4}}; 是合法的,而 int a[][] = {{1, 2}, {3, 4}}; 是不合法的。
扫雷
C++时间 1 s内存 512 MB标准输入输出
小杨同学正在游玩经典游戏「扫雷」,他想自己生成一个「扫雷」的地图。
小杨同学希望生成的地图大小为 n 行 m 列,一共 n×m 个区块。区块行号为 1,2,⋯,n,列号为 1,2,⋯,m。其中一些区块为雷区,其它区块不为雷区。
小杨同学指定了 q 个区块为雷区,而其它区块均不为雷区。小杨同学希望你帮忙计算非雷区的区块,每个区块与多少个雷区相邻?
我们定义区块相邻,当且仅当两个区块至少有一个公共顶点(也就是说对于不在地图边缘的区块,周围 8 个区块均与其相邻)。
输入格式
输入包含 q+1 行。
第一行,三个正整数 n, m 和 q,分别表示地图行数和列数,以及雷区数量。
接下来的 q 行,每行有 2 个整数,分别表示第 i 个雷区的行号和列号。
保证输入的雷区不重复。
输出格式
输出 n 行,每行 m 个字符(使用空格分割),对于第 i 行第 j 列,输出地图对应区块的信息:
- 如果为雷区,输出
*; - 如果不是雷区,输出其相邻雷区数量(输出 0 到 8 中的一个数字)。
样例
3 4 4 1 1 1 3 2 4 3 2
* 2 * 2 2 3 3 * 1 * 2 1
输出解释 1
根据输入,在 3×4 的地图上有 4 个雷区,分别是 (1,1),(1,3),(2,4) 和 (3,2),如输出样例中 * 所示,其它非雷区区块的相邻雷区数量可以直观看出。
数据范围
3≤n,m≤500, 1≤q≤n⋅m。
输入的雷区必定在地图内且不重复,注意行号和列号均从 1 开始。
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB