当前位置: 首页 > news >正文

CCF-CSP 2024 --重塑矩阵1,2c语言题解

  创作想法是因为像我当初大一时候想参加一些比赛但是奈何只学了c和c相关数据结构,但是对于许多竞赛的题目的题解往往都是c++或者其他面向对象的编程语言,让我们难以在c语言基础上入手这些比较复杂的题目。

  创造的目的是为了帮助各位同时提高我对c语言编程的理解和锻炼个人能力,废话不多说上菜!!

1.矩阵重塑(其一)

刷新 

时间限制: 1.0 秒

空间限制: 512 MiB

相关文件: 题目目录(样例文件)

题目背景

矩阵(二维)的重塑(reshape)操作是指改变矩阵的行数和列数,同时保持矩阵中元素的总数不变。

题目描述

矩阵的重塑操作可以具体定义为以下步骤:

设原矩阵为 𝑀M,其维度为 𝑛×𝑚n×m,即有 𝑛n 行和 𝑚m 列。新矩阵为 𝑀′M′,其维度为 𝑝×𝑞p×q。重塑操作要满足 𝑛×𝑚=𝑝×𝑞n×m=p×q,这保证了元素的总数不变。

  1. 线性化原矩阵:按照行优先的顺序,将原矩阵 𝑀M 的元素转换成一个长度为 𝑛×𝑚n×m 的一维数组 𝐴A。这意味着你先读取 𝑀M 的第 00 行元素,然后是第 11 行,依此类推,直到最后一行。
  2. 填充新矩阵:使用一维数组 𝐴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′。

输入格式

从标准输入读入数据。

输入共 𝑛+1n+1 行。

输入的第一行包含四个正整数 𝑛n、𝑚m 和 𝑝p、𝑞q

接下来依次输入原矩阵 𝑀M 的第 00 到第 𝑛−1n−1 行,每行包含 𝑚m 个整数,按列下标从 00 到 𝑚−1m−1 的顺序依次给出。

输出格式

输出到标准输出。

输出共 𝑝p 行,每行 𝑞q 个整数,表示重塑后的矩阵 𝑀′M′。输出格式与输入相同,即依次输出 𝑀′M′ 的第 00 行到第 𝑝−1p−1 行;行内按列下标从 00 到 𝑞−1q−1 的顺序输出,且两个整数间仅用一个空格分隔。

样例1输入

2 3 3 2
1 2 3
4 5 6

样例1输出

1 2
3 4
5 6

样例2输入

2 2 1 4
6 6
6 6

样例2输出

6 6 6 6

子任务

全部的测试数据满足:

  • 𝑛n、𝑚m 和 𝑝p、𝑞q 均为正整数且 𝑛×𝑚=𝑝×𝑞≤104n×m=p×q≤104;
  • 输入矩阵中每个元素的绝对值不超过 10001000。

来自 <TUOJ>

tip:上面看不请 我在单独拿出来 

主函数部分------

具体函数部分--------

然后实现功能 即可通过:

下面是完整代码:

#include<stdlib.h>
#include<stdio.h>int** RecreatMatrix(int** a, int n, int m, int p, int q)
{// 变量初始  int* tmp = (int*)malloc(n*m*sizeof(int));// 中间矩阵int size = 0;// for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){tmp[size++]=a[i][j];}}// 创建目标矩阵 obj int** obj = (int**)malloc(p * sizeof(int*));for (int i = 0; i < p; i++){obj[i] = (int*)malloc(q * sizeof(int));}// 存放元素吧for (int i = 0; i < n; i++){free(a[i]);}free(a);int x = 0;for (int i = 0; i < p; i++){for (int j = 0; j < q; j++){obj[i][j] = tmp[x];x++;}}return obj;
}int main()
{int n = 0;int m = 0;int p = 0;int q = 0;scanf("%d %d %d %d",&n,&m,&p,&q);int** matrix = (int**)malloc( n*sizeof(int*));for (int i = 0;i < n; i++){matrix[i] = (int*)malloc(m*sizeof(int));}for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){scanf("%d", &matrix[i][j]);}}// 调用函数 更改行和列 matrix = RecreatMatrix(matrix,n, m, p, q);for (int i = 0; i < p; i++){for (int j = 0; j < q; j++){printf("%d ", matrix[i][j]);}printf("\n");}//确保严谨 记得销毁哦 遍历的类似思路可以拿过来for (int i = 0; i < p; i++){free(matrix[i]);}free(matrix);matrix = NULL;return 0;
}

2.重塑矩阵二----依然动态实现

时间限制: 1.0 秒

空间限制: 512 MiB

相关文件: 题目目录(样例文件)

题目背景

矩阵转置操作是将矩阵的行和列交换的过程。在转置过程中,原矩阵 𝐴A 的元素 𝑎𝑖𝑗aij 会移动到转置后的矩阵 𝐴𝑇AT 的 𝑎𝑗𝑖aji 的位置。这意味着 𝐴A 的第 𝑖i 行第 𝑗j 列的元素在 𝐴𝑇AT 中成为了第 𝑗j 行第 𝑖i 列的元素。

例如,有矩阵 𝐴A 如下:

𝐴=[𝑎𝑏𝑐𝑑𝑒𝑓]A=[adbecf]

它的转置矩阵 𝐴𝑇AT 会是:

𝐴𝑇=[𝑎𝑑𝑏𝑒𝑐𝑓]AT=abcdef​​

矩阵转置在线性代数中是一个基本操作,广泛应用于各种数学和工程领域。

题目描述

给定 𝑛×𝑚n×m 的矩阵 𝑀M,试编写程序支持以下查询和操作:

  1. 重塑操作 𝑝p𝑞q:将当前矩阵重塑为 𝑝×𝑞p×q 的形状(重塑的具体定义见上一题);
  2. 转置操作:将当前矩阵转置;
  3. 元素查询 𝑖i𝑗j:查询当前矩阵第 𝑖i 行 𝑗j 列的元素(0≤𝑖<𝑛0≤i<n 且 0≤𝑗<𝑚0≤j<m)。

依次给出 𝑡t 个上述查询或操作,计算其中每个查询的结果。

输入格式

从标准输入读入数据。

输入共 𝑛+𝑡+1n+t+1 行。

输入的第一行包含三个正整数 𝑛n𝑚m 和 𝑡t

接下来依次输入初始矩阵 𝑀M 的第 00 到第 𝑛−1n−1 行,每行包含 𝑚m 个整数,按列下标从 00 到 𝑚−1m−1 的顺序依次给出。

接下来输入 𝑡t 行,每行包含形如 op a b 的三个整数,依次给出每个查询或操作。具体输入格式如下:

  • 重塑操作:1 p q
  • 转置操作:2 0 0
  • 元素查询:3 i j

输出格式

输出到标准输出。

每个查询操作输出一行,仅包含一个整数表示查询结果。

样例1输入

解释

3 2 3
1 2
3 4
5 6
3 0 1
1 2 3
3 1 2

样例1输出

2
6

样例2输入

解释

3 2 5
1 2
3 4
5 6
3 1 0
2 0 0
3 1 0
1 3 2
3 1 0

样例2输出

3
2
5

初始矩阵: [123456]135246​​, (1,0)(1,0) 位置元素为 33

转置后: [135246][123456], (1,0)(1,0) 位置元素为 22

重塑后: [135246]154326​​, (1,0)(1,0) 位置元素为 55

子任务

8080 的测试数据满足:

  • 𝑡≤100t≤100

全部的测试数据满足:

  • 𝑡≤105t≤105 且其中转置操作的次数不超过 100100
  • 𝑛n𝑚m 和所有重塑操作中的 𝑝p𝑞q 均为正整数且 𝑛×𝑚=𝑝×𝑞≤104n×m=p×q≤104
  • 输入矩阵中每个元素的绝对值不超过 10001000

提示

  • 对于 𝑛×𝑚n×m 的矩阵,虽然转置和重塑操作都可以将矩阵形态变为 𝑚×𝑛m×n,但这两种操作通常会导致不同的结果。
  • 评测环境仅提供各语言的标准库,特别地,不提供任何线性代数库(如 numpypytorch 等)。

来自 <TUOJ>

完整代码:

#include<stdlib.h>
#include<stdio.h>
int** RecreatMatrix(int** a, int n, int m, int p, int q)
{// 变量初始  int* tmp = (int*)malloc(n*m*sizeof(int));// 中间矩阵int size = 0;// for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){tmp[size++]=a[i][j];}}// 创建目标矩阵 obj int** obj = (int**)malloc(p * sizeof(int*));for (int i = 0; i < p; i++){obj[i] = (int*)malloc(q * sizeof(int));}// 存放元素吧for (int i = 0; i < n; i++){free(a[i]);}free(a);int x = 0;for (int i = 0; i < p; i++){for (int j = 0; j < q; j++){obj[i][j] = tmp[x];x++;}}return obj;
}int** transpose(int** a, int n, int m)
{int p = m;int q = n;int** obj = (int**)malloc(p * sizeof(int*));for (int i = 0; i < p; i++){obj[i] = (int*)malloc(q * sizeof(int));}for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){obj[j][i] = a[i][j];}}// 记得销毁哦for (int i = 0; i < n; i++){free(a[i]);}free(a);return obj;}// 查询功能
int Find_x(int** a,int i, int j)
{return a[i][j];
}int main()
{int n = 0;int m = 0;int t = 0;scanf("%d %d %d", &n, &m, &t);int** matrix = (int**)malloc(n * sizeof(int*));for (int i = 0; i < n; i++){matrix[i] = (int*)malloc(m * sizeof(int));}for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){scanf("%d", &matrix[i][j]);}}// 进入功能使用部分while (t--){int input = 0;scanf("%d",&input);if (input == 1){int p = 0;int q = 0;scanf("%d %d", &p, &q);matrix = RecreatMatrix(matrix, n, m, p, q);n = p;m = q;}else if (input == 2){int p = 0;int q = 0;scanf("%d %d", &p, &q);matrix = transpose(matrix, n,  m);int tmp = n;n = m;m = tmp;}else if (input == 3){int i = 0;int j = 0;scanf("%d %d", &i, &j);int x = Find_x(matrix,i,j);printf("%d\n",x);}}for (int i = 0; i < n; i++){free(matrix[i]);}free(matrix);}

3. 思路的缺陷-----以及建议

缺陷

  (重塑矩阵二)简单发现代码提交之后会存在一些测试案例显示占用内存空间超出限制,这里我认为因为其中主要原因是因为:

  频繁使用malloc这样的动态内存分布函数使得堆上的内存使用free后内存碎片化,使得之后没有一块连续的足够大的内存存放数据。

  另一个缺陷就是我们使用malloc函数的时候都没有判空,其实严谨来说咱还是判空一下(读者自行解决咯)

建议

 其实我们可以创建静态矩阵来存放数据,初始化该矩阵直接最大值即可,然后开始实现吧。

我这里仅对重塑矩阵部分进行提示,其他部分都很简单大家自己想想吧。

  这里我们要用到数组指针。传递二维数组嘛

是吧更加简单明了。

  好的这期就到这里非常感谢各位的支持你的小红心就是对我最大的鼓励。谢谢咯

补充: 非常抱歉,经过我后面再度调试发现我们的动态其实能过。

之所以前面内存超载了,是因为我在一个重塑矩阵函数中忘记释放一个中间载体一维数组了。

修改之后就是加一个free(tmp)即可。

至于前面的建议也可以采纳,以及对于malloc的缺陷也可以了解一下我就不删除了。谢谢咯

相关文章:

  • 网络编程9.3
  • 基础学习之——Kubernetes
  • vscode好用的快捷键整理~
  • 基础学习之——Docker Compose的安装和使用
  • 不管夫妻还是情人,想要长相厮守、生活幸福美满,就这两个字!
  • 宁波银行资产规模首超3万亿,高成长性被机构清一色看好
  • 维度不固定的多维数组形参笔记
  • Swift 运算符
  • spring boot 项目 prometheus 自定义指标收集区分应用环境集群实例ip,使用 grafana 查询--方法耗时分位数指标
  • HarmonyOS 开发范式、应用模型
  • Electron 项目实战 02:打包和自动更新
  • 有temp表包含A,B两列,使用SQL,对B列进行处理,形成C列,按A列顺序,B列值不变,则C列累计技术,B列值变化,则C列重新开始计数
  • 数据库课程设计mysql---图书管理系统详细的设计文档和需求文档
  • TCP如何关闭连接(详细版)
  • 如何进行 AWS 云监控
  • 分享一款快速APP功能测试工具
  • 【技术性】Search知识
  • 30秒的PHP代码片段(1)数组 - Array
  • Angular Elements 及其运作原理
  • Logstash 参考指南(目录)
  • MySQL几个简单SQL的优化
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • SpringBoot 实战 (三) | 配置文件详解
  • 程序员最讨厌的9句话,你可有补充?
  • 基于遗传算法的优化问题求解
  • 前端_面试
  • 微信开放平台全网发布【失败】的几点排查方法
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 【云吞铺子】性能抖动剖析(二)
  • hi-nginx-1.3.4编译安装
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • 第二十章:异步和文件I/O.(二十三)
  • ​1:1公有云能力整体输出,腾讯云“七剑”下云端
  • ​第20课 在Android Native开发中加入新的C++类
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (3) cmake编译多个cpp文件
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (javascript)再说document.body.scrollTop的使用问题
  • (web自动化测试+python)1
  • (补充):java各种进制、原码、反码、补码和文本、图像、音频在计算机中的存储方式
  • (二)JAVA使用POI操作excel
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (一) 初入MySQL 【认识和部署】
  • (一一四)第九章编程练习
  • (转)JAVA中的堆栈
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • .net通用权限框架B/S (三)--MODEL层(2)
  • @angular/cli项目构建--http(2)