赞
踩
这道题是一道差分算法的拓展题型,是算法刷题笔记到目前为止我认为最困难的题目之一。因此,这篇题解博客的过程记录也最为详细,希望能够为你带来帮助。
n
行m
列的整数矩阵,再输入q
个操作,每个操作包含五个整数 x1,y1,x2,y2,c
,其中 (x1,y1)
和(x2,y2)
表示一个子矩阵的左上角坐标和右下角坐标。c
。输入格式
n
,m
,q
。n
行,每行包含m
个整数,表示整数矩阵。q
行,每行包含5个整数x1
,y1
,x2
,y2
,c
,表示一个操作。输出格式
n
行,每行m
个整数,表示所有操作进行完毕后的最终矩阵。数据范围
1 ≤ n,m ≤ 1000
,1 ≤ q ≤ 100000
,1≤x1≤x2≤n
,1≤y1≤y2≤m
,−1000≤c≤1000
,−1000≤矩阵内元素的值≤1000
完整的C++解题代码如下所示:
#include <cstdio> const int N(1010); int matrix[N][N]; int dif_matrix[N][N]; // C++中整数类型的二维数组中的所有元素都会被初始化为0 //用于逐步构建差分矩阵的函数 inline void insert_to_matrix(const int& x1, const int& y1, const int& x2, const int& y2, const int& c) { dif_matrix[x1][y1] += c; dif_matrix[x1][y2 + 1] -= c; dif_matrix[x2 + 1][y1] -= c; dif_matrix[x2 + 1][y2 + 1] += c; } int main(void) { // 变量定义 int n, m, q; // 变量输入 scanf("%d %d %d", &n, &m, &q); // 根据输入构造差分矩阵(行列下标都从1开始,更加方便) for(int i(1); i <= n; ++i) { for(int j(1); j <= m; ++j) { int x; scanf("%d", &matrix[i][j]); insert_to_matrix(i, j, i, j, matrix[i][j]); } } // 构造差分矩阵 for(int i(0); i < q; ++i) { int x1, y1, x2, y2, c; scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &c); insert_to_matrix(x1, y1, x2, y2, c); } // 差分矩阵构造完成,根据差分矩阵递推出原矩阵并输出 for(int i(1); i <= n; ++i) { for(int j(1); j <= m; ++j) { dif_matrix[i][j] += (dif_matrix[i - 1][j] + dif_matrix[i][j - 1] - dif_matrix[i - 1][j - 1]); printf("%d ", dif_matrix[i][j]); } printf("\n"); } }
下面将对代码进行逐部分讲解。
第一部分:
#include <cstdio>
const int N(1010);
int matrix[N][N];
int dif_matrix[N][N]; // C++中整数类型的二维数组中的所有元素都会被初始化为0
cstdio
,因为需要使用其中的scanf
函数和printf
函数分别进行变量的输入和结果的输出。之所以使用这两个C语言中的输入输出函数而不是C++中的cin
和cout
对象,是因为本题中的输入输出都涉及矩阵,数据量较大,使用这两个函数的效率远高于使用cin
和cout
。1010
的整数常量,这是因为根据题目中的数据范围,矩阵的行和列都不会超过1000
,而为了防止编程过程中二维数组的访问越界,用一个比1000
稍大的数字更好,此处选用1010
,用于表示二维数组的最大行数和列数。这个二维数组在所有函数之外进行声明和创建,因此是一个静态数组。静态数组中所有元素都会被默认初始化为0,这就方便了我们后续对该数组的使用。matrix
是指原始矩阵,即用户输入的值构成的矩阵;dif_matrix
即为差分矩阵。第二部分
int main(void) { // 变量定义 int n, m, q; // 变量输入 scanf("%d %d %d", &n, &m, &q); // 根据输入构造差分矩阵(行列下标都从1开始,更加方便) for(int i(1); i <= n; ++i) { for(int j(1); j <= m; ++j) { int x; scanf("%d", &matrix[i][j]); insert_to_matrix(i, j, i, j, matrix[i][j]); } }
cin
效率更高的scanf
函数读入三个变量,然后根据用户的输入给二维数组中的指定位置插入元素,创建一个模拟的矩阵。0
开始使用,而是从1
开始使用,这是因为用户在后续查询过程中都是输入的数组的行号和列号,两者都不为零,此处将下标从1
开始便于和后面的过程保持一致。scanf
函数输入一个矩阵元素,程序都会使用insert_to_matrix
函数来根据该元素的值修改差分矩阵中的内容(起初差分矩阵中的值都是0),这个函数的详细解释请看下面的第三部分。此处将插入的坐标设置为一个单元格。第三部分
//用于逐步构建差分矩阵的函数
inline void insert_to_matrix(const int& x1, const int& y1, const int& x2, const int& y2, const int& c)
{
dif_matrix[x1][y1] += c;
dif_matrix[x1][y2 + 1] -= c;
dif_matrix[x2 + 1][y1] -= c;
dif_matrix[x2 + 1][y2 + 1] += c;
}
inline
内联函数有可能可以提高执行效率。c
,即传入的最后一个参数。具体的公式推导略,可以通过简答的画图理解公式的内容。第四部分
// 构造差分矩阵
for(int i(0); i < q; ++i)
{
int x1, y1, x2, y2, c;
scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &c);
insert_to_matrix(x1, y1, x2, y2, c);
}
第五部分
// 差分矩阵构造完成,根据差分矩阵递推出原矩阵并输出
for(int i(1); i <= n; ++i)
{
for(int j(1); j <= m; ++j)
{
dif_matrix[i][j] += (dif_matrix[i - 1][j] + dif_matrix[i][j - 1] - dif_matrix[i - 1][j - 1]);
printf("%d ", dif_matrix[i][j]);
}
printf("\n");
}
\n
。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。