应该是第10次上机题目了,本次共10道题(由于具体输入输出的样例题目中都有,就不在博客里占篇幅复制粘贴了,只把题题目和要求赋值过来):
7-1 | 求矩阵的局部极大值 |
7-2 | 矩阵运算 |
7-3 | 方阵循环右移 |
7-4 | 判断上三角矩阵 |
7-5 | 找鞍点 |
7-6 | 打印杨辉三角 |
7-7 | 螺旋方阵 |
7-8 | 求矩阵各行元素之和 |
7-9 | 矩阵A乘以B |
7-10 | 组合数的和 |
7-1 求矩阵局部极大值
给定M行N列的整数矩阵A,如果A的非边界元素A[i][j]大于相邻的上下左右4个元素,那么就称元素A[i][j]是矩阵的局部极大值。本题要求给定矩阵的全部局部极大值及其所在的位置。
输入格式:
在第一行中给出矩阵A的行数M和列数N(3 ≤ M, N ≤ 20);最后M行,每行给出A在该行的N个元素的值。数字间以空格分隔。
输出格式:
每行按照“元素值 行号 列号”的格式输出一个局部极大值,其中行、列编号从1开始。要求按照行号递增输出;若同行有超过1个局部极大值,则该行按列号递增输出。若没有局部极大值,则输出“None 总行数 总列数”。
解:
这道题很简单,就是对于第2行到倒数第2行,第2列到倒数第2列,找有没有比上下左右都大的数(边界不需要判断),因为最小也是3列所以没有极端情况需要判断。注意输出行列的时候+1就行(因为从1开始)。
#include <stdio.h>
int main()
{
int M, N, flag = 0;
scanf("%d%d", &M, &N);
int a[M][N];
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
scanf("%d", &a[i][j]);
for(int i = 1; i < M - 1; i++)
for(int j = 1; j< N - 1; j++)
if(a[i][j] > a[i - 1][j] && a[i][j] > a[i + 1][j] && a[i][j] > a[i][j - 1] && a[i][j] > a[i][j + 1])
{
printf("%d %d %d\n", a[i][j], i + 1, j + 1);
flag = 1;
}
if(flag == 0) printf("None %d %d\n", M, N);
return 0;
}
7-1 矩阵运算
给定一个n×n的方阵,本题要求计算该矩阵除副对角线、最后一列和最后一行以外的所有元素之和。副对角线为从矩阵的右上角至左下角的连线。
输入格式:
输入第一行给出正整数n(1<n≤10);随后n行,每行给出n个整数,其间以空格分隔。
输出格式:
在一行中给出该矩阵除副对角线、最后一列和最后一行以外的所有元素之和。
解:
只需要判断好副对角线,最后一列,最后一行就没有任何难度。
#include <stdio.h>
int main()
{
int n, sum = 0;
scanf("%d", &n);
int a[n][n];
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
scanf("%d", &a[i][j]);
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if((i + j) != n - 1 && j != n - 1 && i != n - 1) // 不是副对角线,不是最后一列,不是最后一行
sum += a[i][j];
printf("%d\n", sum);
return 0;
}
7-3 方阵循环右移
本题要求编写程序,将给定n×n方阵中的每个元素循环向右移m个位置,即将第0、1、⋯、n−1列变换为第n−m、n−m+1、⋯、n−1、0、1、⋯、n−m−1列。
输入格式:
输入第一行给出两个正整数m和n(1 ≤ n ≤ 6)。接下来一共n行,每行n个整数,表示一个n阶的方阵。
输出格式:
按照输入格式输出移动后的方阵:即输出n行,每行n个整数,每个整数后输出一个空格。
解:
这道题需要考虑 m > n 的情况,而且比如 3x3 的方阵,右移100位,也就是右移1位,因为每移动 n 位,就相当于没动。也就是说,相当于右移 m % n 位。
因为每一行之间没有任何关系,所以可以读取一行,右移一行,输出一行,再继续。所以只需要一个大小为n的数组就行了。而且因为只需要输出,所以甚至不需要交换,或者真的去移动数组,而是按照右移后的顺序输出就行了。比如 1 2 3 4 5,右移 2 位,不需要右移,先输出 4 5,再输出 1 2 3 就行了。分界线为 n - m。
#include <stdio.h>
int main()
{
int m, n; // n个大小为n的数组,都右移m个位置
scanf("%d%d", &m, &n);
m %= n;
int a[n];
for(int row = 0; row < n; row++)
{
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
for(int i = n - m; i < n; i++) printf("%d ", a[i]);
for(int i = 0; i < n - m; i++) printf("%d ", a[i]);
printf("\n");
}
return 0;
}
7-4 判断上三角矩阵
上三角矩阵指主对角线以下的元素都为0的矩阵;主对角线为从矩阵的左上角至右下角的连线。
本题要求编写程序,判断一个给定的方阵是否上三角矩阵。
输入格式:
输入第一行给出一个正整数T,为待测矩阵的个数。接下来给出T个矩阵的信息:每个矩阵信息的第一行给出一个不超过10的正整数n。随后n行,每行给出n个整数,其间以空格分隔。
输出格式:
每个矩阵的判断结果占一行。如果输入的矩阵是上三角矩阵,输出“YES”,否则输出“NO”。
解:
只需要判断下三角有没有不是0的就行,for(int i = 1; i < n; i++) 和 for(int j = 0; j < i; j++) 连个循环条件想明白就明白了。
#include <stdio.h>
int main()
{
int repeat;
scanf("%d", &repeat);
while(repeat > 0) // 重复 repeat 次
{
int n, flag = 0;
scanf("%d", &n);
int a[n][n];
for(int i = 0; i < n; i++)
for(int j = 0; j <n; j++)
scanf("%d", &a[i][j]);
for(int i = 1; i < n; i++) // 从第二行开始
{
for(int j = 0; j < i; j++) // 每行判断前 i 个数有没有不是0的
if(a[i][j] != 0)
{
printf("NO\n");
flag = 1;
break;
}
if(flag == 1) break;
}
if(flag == 0) printf("YES\n");
--repeat;
}
return 0;
}
7-5 找鞍点
一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。
本题要求编写程序,求一个给定的n阶方阵的鞍点。
输入格式:
输入第一行给出一个正整数n(1≤n≤6)。随后n行,每行给出n个整数,其间以空格分隔。
输出格式:
输出在一行中按照“行下标 列下标”(下标从0开始)的格式输出鞍点的位置。如果鞍点不存在,则输出“NONE”。题目保证给出的矩阵至多存在一个鞍点。
解:
这题需要注意的地方就是,一行中可能有多个相同大小的最大值,比如 1 5 2 3 5 5,每一个最大值都需要判断是不是鞍点。
#include <stdio.h>
int main()
{
int n, flag = 0;
scanf("%d", &n);
int a[6][6] = {0};
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
scanf("%d", &a[i][j]);
for(int i = 0; i < n; i++)
{
int maxA = -9999999, k, t;
for(int j = 0; j < n; j++) // 找出第 i 行最大值是多少
if(a[i][j] > maxA)
maxA = a[i][j];
for(t = 0; t < n; t++) // 对每一个最大值位置都判断是不是鞍点
{
if(a[i][t] != maxA) continue;
for(k = 0; k < n; k++)
if(a[k][t] < a[i][t])
break;
if(k == n)
{
flag = 1;
printf("%d %d\n", i, t);
return 0;
}
}
}
if(flag == 0) printf("NONE\n");
return 0;
}
7-6 打印杨辉三角
本题要求按照规定格式打印前N行杨辉三角。
输入格式:
输入在一行中给出N(1 ≤ N ≤ 10)。
输出格式:
以正三角形的格式输出前N行杨辉三角。每个数字占固定4位。
输入样例: 6
输出样例:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
解:
这道题很多人卡在了“格式错误”上,格式错误是真的坑爹= =。
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
int a[n][n];
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n - i - 1; j++) printf(" "); // 第 i 行有 n - i - 1 个前缀空格
a[i][0] = 1; // 每行第一个数是1
a[i][i] = 1; // 每行最后一个数是1
for(int j = 1; j < i; j++)
a[i][j] = a[i - 1][j - 1] + a[i - 1][j];
for(int j = 0; j <= i; j++)
printf("%4d", a[i][j]);
printf("\n");
}
return 0;
}
7-7 螺旋方阵
所谓“螺旋方阵”,是指对任意给定的N,将1到N×N的数字从左上角第1个格子开始,按顺时针螺旋方向顺序填入N×N的方阵里。本题要求构造这样的螺旋方阵。
输入格式:
输入在一行中给出一个正整数N(<10)。
输出格式:
输出 N×N 的螺旋方阵。每行N个数字,每个数字占3位。
输入样例: 5
输出样例:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
解:
很多同学这道题没有思路,但是其实看一下矩阵就知道思路了。就是一个大循环,循环里先最上边一行从左到右,再最右边一列从上到下,再最下边一行从右到左,再最左边一列从下到上,一次循环就结束了,二维矩阵所有位置赋值之后,按照顺序输出就行了。注意每次赋值的边界判断:
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
int a[n][n];
int T = 0, D = n - 1, L = 0, R = n - 1, cur = 1; // Top, Down, Left, Right
while (T <= D && L <= R)
{
for (int col = L; col <= R; col++) // 最上边一行从左到右
a[T][col] = cur++;
++T;
for (int row = T; row <= D; row++) // 最右边一列从上到下
a[row][R] = cur++;
--R;
for (int col = R; col >= L; col--) // 最下边一行从右到左
a[D][col] = cur++;
--D;
for (int row = D; row >= T; row--) // 最左边一列从下到上
a[row][L] = cur++;
++L;
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
printf("%3d", a[i][j]);
printf("\n");
}
return 0;
}
7-8 求矩阵各行元素之和
本题要求编写程序,求一个给定的m×n矩阵各行元素之和。
输入格式:
输入第一行给出两个正整数m和n(1 ≤ m, n ≤ 6)。随后m行,每行给出n个整数,其间以空格分隔。
输出格式:
每行输出对应矩阵行元素之和。
解:
没任何难度。每读一行,输出一行。
#include <stdio.h>
int main()
{
int m, n;
scanf("%d%d", &m, &n);
while(m > 0) // m行
{
int sum = 0;
for(int i = 0; i < n; i++)
{
int tmp;
scanf("%d", &tmp);
sum += tmp;
}
printf("%d\n", sum);
--m;
}
return 0;
}
7-9 矩阵A乘以B
给定两个矩阵A和B,要求你计算它们的乘积矩阵AB。需要注意的是,只有规模匹配的矩阵才可以相乘。即若A有Ra行、Ca列,B有Rb行、Cb列,则只有Ca与Rb相等时,两个矩阵才能相乘。
输入格式:
输入先后给出两个矩阵A和B。对于每个矩阵,首先在一行中给出其行数R和列数C,随后R行,每行给出C个整数,以1个空格分隔,且行首尾没有多余的空格。输入保证两个矩阵的R和C都是正数,并且所有整数的绝对值不超过100。
输出格式:
若输入的两个矩阵的规模是匹配的,则按照输入的格式输出乘积矩阵AB,否则输出Error: Ca != Rb
,其中Ca
是A的列数,Rb
是B的行数。
解:
按照矩阵乘法公式计算即可。
#include<stdio.h>
int main()
{
int ra, ca, rb, cb;
scanf("%d%d", &ra, &ca);
int a[ra][ca];
for(int i = 0; i < ra; i++)
for(int j = 0; j < ca; j++)
scanf("%d", &a[i][j]);
scanf("%d%d", &rb, &cb);
int b[rb][cb];
for(int i = 0; i < rb; i++)
for(int j = 0; j < cb; j++)
scanf("%d", &b[i][j]);
// 如果矩阵1的列数不等于矩阵2的行数,则报错退出
if(ca != rb) printf("Error: %d != %d\n", ca, rb);
else
{
printf("%d %d\n", ra, cb);
for(int i = 0; i < ra; i++)
for(int j = 0; j < cb; j++)
{
int sum=0;
for(int k = 0; k < ca; k++)
sum += a[i][k] * b[k][j];
if(j < cb - 1) printf("%d ",sum);
else printf("%d\n",sum);
}
}
return 0;
}
7-10 组合数的和
给定 N 个非 0 的个位数字,用其中任意 2 个数字都可以组合成 1 个 2 位的数字。要求所有可能组合出来的 2 位数字的和。例如给定 2、5、8,则可以组合出:25、28、52、58、82、85,它们的和为330。
输入格式:
输入在第一行中给出 N(1 < N < 10),随后一行给出 N 个不同的非 0 个位数字。数字间以空格分隔。
输出格式:
输出所有可能组合出来的2位数字的和。
解:
“不同”两个字把难度又降了不少,把所有数字读到一个数组中,然后遍历就好了。
#include <stdio.h>
int main()
{
int n,sum = 0;
scanf("%d", &n);
int a[n];
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(i != j)
sum += a[i] * 10 + a[j];
printf("%d\n", sum);
return 0;
}