第一题
题目背景
矩阵(二维)的重塑(reshape)操作是指改变矩阵的行数和列数,同时保持矩阵中元素的总数不变。
题目描述
矩阵的重塑操作可以具体定义为以下步骤:
设原矩阵为 𝑀M,其维度为 𝑛×𝑚n×m,即有 𝑛n 行和 𝑚m 列。新矩阵为 𝑀′M′,其维度为 𝑝×𝑞p×q。重塑操作要满足 𝑛×𝑚=𝑝×𝑞n×m=p×q,这保证了元素的总数不变。
线性化原矩阵:按照行优先的顺序,将原矩阵 𝑀M 的元素转换成一个长度为 𝑛×𝑚n×m 的一维数组 𝐴A。这意味着你先读取 𝑀M 的第 00 行元素,然后是第 11 行,依此类推,直到最后一行。
填充新矩阵:使用一维数组 𝐴A 中的元素按照行优先的顺序填充新矩阵 𝑀′M′。首先填充 𝑀′M′ 的第 00 行,直到该行有 𝑞q 个元素,然后继续填充第 11 行,直到所有 𝑝p 行都被填满。
给定原矩阵中的一个元素的位置 (𝑖,𝑗)(i,j)(0≤𝑖<𝑛0≤i<n 且 0≤𝑗<𝑚0≤j<m),我们可以找到这个元素在被线性化后的一维数组 𝐴A 中的位置 𝑘k(0≤𝑘<𝑛×𝑚0≤k<n×m),然后确定它在新矩阵 𝑀′M′ 中的位置 (𝑖′,𝑗′)(i′,j′)(0≤𝑖′<𝑝0≤i′<p 且 0≤𝑗<𝑞0≤j<q)。它们之间满足如下数学关系:𝑖×𝑚+𝑗=𝑘=𝑖′×𝑞+𝑗′i×m+j=k=i′×q+j′
给定 𝑛×𝑚n×m 的矩阵 𝑀M 和目标形状 𝑝p、𝑞q,试将 𝑀M 重塑为 𝑝×𝑞p×q 的矩阵 𝑀′M′。
由上面题目知道这题就是简单的矩阵处理,但是注意到下面的n和m的取值范围级别的,显然若只用普通二维矩阵存储的方式可能不是很好的解决策略。
我们注意到本题只是让我们输出变换后的矩阵,而变换的最重要的一步就是将其填充至一维数组中取,因此,不妨可以不用将其变换后的存入矩阵中,可以直接输出即可,这样可以节约大量的空间和做题时间。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int m, n, p, q, arr[100001],ch,t=1;
cin >> n >> m >> p >> q;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> ch;
arr[t++] = ch;
}
}
t = 1;
for (int i = 1; i <= p; i++)
{
for (int j = 1; j <= q; j++)
{
cout << arr[t++]<<" ";
}
cout << endl;
}
}
第二题
矩阵转置操作是将矩阵的行和列交换的过程。在转置过程中,原矩阵 A 的元素
会移动到转置后的矩阵
的
的位置。这意味着 A 的第 i 行第 j 列的元素在
中成为了第 j 行第 i 列的元素。
例如,有矩阵 A 如下:
它的转置矩阵
会是:
矩阵转置在线性代数中是一个基本操作,广泛应用于各种数学和工程领域。
题目描述
给定 𝑛×𝑚n×m 的矩阵 𝑀M,试编写程序支持以下查询和操作:
重塑操作 𝑝p、𝑞q:将当前矩阵重塑为 𝑝×𝑞p×q 的形状(重塑的具体定义见上一题);
转置操作:将当前矩阵转置;
元素查询 𝑖i、𝑗j:查询当前矩阵第 𝑖i 行 𝑗j 列的元素(0≤𝑖<𝑛0≤i<n 且 0≤𝑗<𝑚0≤j<m)。
依次给出 𝑡t 个上述查询或操作,计算其中每个查询的结果。
第二题是在第一题的基础上的,我们可以借鉴第一题的思路,用一个一维数组记录他的元素的相对顺序,再用p,q记录修改后的维度。
首先确定转置时原数组与转置后的关系,由基本的矩阵结论可以推出:
假设原矩阵为维的m1,转置后为m2,则其元素间存在如下关系:
其中tt是原矩阵的元素序号。
因此,源程序如下:
#include<bits/stdc++.h>
using namespace std;
void zz(int m2[], int m1[], int p, int q)
{
int i, j, tt;
for (tt = 0; tt< p * q; tt++)
{
m2[(tt % q) * p + tt/ q] = m1[tt];
}
for (tt = 0; tt < p * q; tt++)
{
m1[tt] = m2[tt];
}
}
int main()
{
int n, m, t, m1[100001], m2[100001],i,j;
cin >> n >> m>>t;
int qt = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
cin >> m1[qt++];
}
}
int op, a, b;
int p=n, q=m;
int flag=0;
for (i = 1; i <= t; i++)
{
cin >> op >> a >> b;
if (op == 1)
{
p = a;
q = b;
flag = 1;
continue;
}
if (op == 2)
{
zz(m2,m1,p,q);
int temp;
temp = p;
p = q;
q = temp;
flag = 2;
}
if (op == 3)
{
if (flag == 0) cout << m1[a*q+b] << endl;
if (flag == 1) cout << m1[a * q + b] << endl;
if (flag == 2) cout << m2[a * q + b] << endl;
}
}
}