小红书C++开发笔试题,6道选择+3道算法题,3道算法题的分值是20,20,40,由于时间不够,最后一题并未AC,下面给出第3道算法题解:
题目描述:
已知一个n×m的矩阵,矩阵中的元素代表金币数量,现在需要从这个n×m的矩阵中,找到一个r×c的子矩阵,要求r×c的子矩阵中每两个相邻元素做差求绝对值,然后求和(相邻表示上下左右,如果在该元素在边界则只求存在的相邻元素即可),问所有可能的r×c子矩阵中,所求和的最小值是多少?
输入描述:
n,m,r,c
接下来的n行,每行包含m个用空格隔开的整数,表示矩阵对应位置元素值
输出描述:
一个整数,表示差值之和的最小值
样例输入:
4 4 2 2
5 4 2 6
4 10 1 8
1 9 3 10
6 4 8 3
样例输出:
4
输出分析:
所选矩阵为{
{6,4},{5,4}},第4行前两个元素和第1行前两个元素(注意:子矩阵的选择不需要在原始矩阵中严格相邻)
题目分析:
题目看似需要求每一个元素的“上下左右”四个相邻元素的差值,其实我们只需要遍历n*m的矩阵,求每个元素与他右侧以及下侧元素的差值即可,而当遍历到边界时,如第一行末尾元素的右侧没有值,这时求该元素和第一行首个元素的差值即可,列边界的求解也同理;
将每个元素与它右侧元素和下侧元素的差值分别存入二维数组中,我们就可以得到两个n×m的差值数组,这里称之为vr和vc,按照样例输入,得到的结果如下:
vr:
1 2 4 1
6 9 7 4
8 6 7 9
2 4 5 3
vc:
1 6 1 2
3 1 2 2
5 5 5 7
1 0 6 3
此时我们分析一下r×c子矩阵的相邻元素差值之和,如果r=3,c=2,任取一子矩阵{
{5,4},{4,10},{1,9}},则在vr中对应的元素为1、6、8(前三行的第一个元素:3×1)),vc中对应的元素为1、6、3、1(前两行的前两个元素:2×2);将3×1,2×2和r=3,c=2对比后不难发现,取vr的r×(c-1)个元素,取vc的(r-1)×c个元素即可;
既然我们已经知道了如何求一个子矩阵的差值之和,那么如何确定是哪一个矩阵呢?其实在原n×m矩阵中,任意一个元素向右(r-1)步,向下(c-1)步,得到的都是符合要求的r×c,只不过遇到边界时我们需要循环到开头,而分析到这里,问题基本上已经可以解决了,我们要做的就是进行遍历,求以当前元素为r×c子矩阵左上角顶点时的相邻元素差的和就可以了。
具体代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
//初始化输入数组
int n = 4, m = 4, r = 2, c = 2;
vector<vector<int>> v =