矩阵类题目 可以锻炼循环和数组(特别是二维的)的运用能力 同时还考验做题人的找规律能力和代码实现能力 大部分属于语法题
下面一起来看看都有什么矩阵吧。
预备知识
首先我们得知道二维数组的定义方法
int a[10][10];
int i=10,j=10;
int a[i][j];
这就是二维数组的常用定义方法 要注意[ ]里面只能是常量 所以里面的i,j我都先赋值了
初始化 可以直接填充 也可以用二重循环输入
#include <stdio.h>
int a[3][3]={1,2,3,4,5,6,7,8,9};
int main(){
for(int i=0;i<=3;i++){
for(int j=0;j<=3;j++){
scanf("%d",&a[i][j]);
}
}
return 0;
}
我们都知道 一维数组用一个循环就可以搞定 那二维数组当然就是二重循环 哈哈很好理解吧
注意 重头戏来了 尽管二维数组在计算机里面是一维记录的 但是你可以把它想象成一个二维矩阵
i是 行 横着的 j是列 竖着的
这对我们 理解题目非常重要 同时 注意数组是从零开始的 也就是说我上面画的这个二维矩阵 左上角第一个点 i=0;j=0 同理右下角 i=2; j=2;
所以其实我们输出也能用二重循环这种朴素的方法
for(int i=0;i<=3;i++){
for(int j=0;j<=3;j++){
printf("%d",a[i][j]);
}
}
好了预备知识就讲这么多吧 再讲下去就变成写数组使用的文章了
1.数组的右下半部分
AcWing 748:输入一个二维数组 M[12][12]M[12][12],根据输入的要求,求出二维数组的右下半部分元素的平均值或元素的和。右下半部分是指次对角线下方的部分,如下图所示,黄色部分为对角线,绿色部分为右部分:
输入格式
第一行输入一个大写字母,若为
S
,则表示需要求出右下半部分的元素的和,若为M
,则表示需要求出右下半部分的元素的平均值。接下来 1212 行,每行包含 1212 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1i+1 行的第 j+1j+1 个数表示数组元素 M[i][j]M[i][j]。
输出格式
输出一个数,表示所求的平均数或和的值,保留一位小数。
数据范围
−100.0≤M[i][j]≤100.0
先来道小菜开开胃 首先观察规律 我们主要是找行和列的规律 我们能发现什么?
没错 聪明的你一定发现了中间的黄线是i=j的坐标 那右半边呢?
对的 右半边所有的坐标和全部都大于12 也就是i+j>12 怎么样 神奇吧
因此我们就有了最简单的一种写法
#include <stdio.h>
char m;
int main()
{
scanf("%d",&m);
double a[12][12],num=0;
for(int i=0; i<12; i++)
{
for(int j=0; j<12; j++)
{
scanf("%d",&a[i][j]);
if(i+j>=12)//关键条件
num=num+a[i][j];
}
}
if(m=='S') printf("%.1f",num);
else printf("%.1f",num/66.0);//右下角和为66 求平均
}
那么 左上部分相信你也会了 不妨试试?
2.数组的左方区域
acwing748:输入一个二维数组 M[12][12]M[12][12],根据输入的要求,求出二维数组的左方区域元素的平均值或元素的和。
数组的两条对角线将数组分为了上下左右四个部分,如下图所示,黄色部分为对角线,绿色部分为左方区域:
输入格式
第一行输入一个大写字母,若为
S
,则表示需要求出左方区域的元素的和,若为M
,则表示需要求出左方区域的元素的平均值。接下来 1212 行,每行包含 1212 个用空格隔开的浮点数,表示这个二维数组,其中第 i+1i+1 行的第 j+1j+1 个数表示数组元素 M[i][j]M[i][j]。
输出格式
输出一个数,表示所求的平均数或和的值,保留一位小数。
数据范围
−100.0≤M[i][j]≤100.0
首先我们还是观察坐标关系 我们可以发现关系为i + j < 11 && i > j
所以我们用坐标肯定是可以做的了
但是 这里我们要用一种进阶的方法 也就是曼哈顿距离法
你不用了解这个名字咋来的 明白用法就好
比如这道题 我们把横坐标/2 纵坐标/2 注意数组坐标是0~11
所以我们中点坐标就是(5.5)然后我们对绿色格子与原点坐标取绝对值abs 就得到了他们的距离
我们发现了什么
对的 这些点和原点的距离全部都<=4.5 这就是曼哈顿距离
所以代码如下
#include<stdio.h>
#include<math.h>//abs函数头文件
int main(){
char a;
scanf("%c", &a);
double n[15][15];//这里用了浮点数输入 你喜欢整型也行
for(int i = 0; i <12 ;i++){ //两个循环输入数组 我假设是一个12行12列的数组
for(int j = 0; j < 12; j++){
scanf("%lf", &n[i][j]);
}
}
for(int i = 0; i < 12; i++){//两个循环遍历12*12的数组
for(int j = 0; j < 12; j++){
if((abs(5.5-i)+j) <= 4.5){ //麦哈顿距离 原点在行i=5.5 列j=0;
//abs表示取绝对值 你那左半边的三角形就是12*12数列左边原点距离在<=4.5范围的数字
//最好去画图理解 然后看看把数组改行改列看还会不会做
printf("%.1lf\n",n[i][j]);
}
}
}
return 0;
}
其实很多题都可以用到曼哈顿距离的思想 比如初学C语言时 肯定都做过这样一道题
叫我们用*号输出一个菱形 ,一般人都是用二重循环找输出几个空格 几个* 但是用曼哈顿距离 这种题根本没那么麻烦
比如一个菱形 ,我们取它的中心点为原点
我们发现了,所有点到原点的距离都<=2
所以代码如下
#include <stdio.h>
#include <math.h>
int main()
{
int n;
scanf("%d",&n);//表示你要几行的菱形 只能是奇数
int sx = n / 2, sy = n / 2;
for (int i = 0; i < n ; i ++ )
{
for (int j = 0; j < n; j ++ )
{
if ( abs(sx - i) + abs(sy - j) <= n / 2 ) printf("*");
else printf(" ");
}
printf("\n");
}
return 0;
}
输出如下:
如果把<=换成==就是一个中空菱形 很神奇吧
3.平方矩阵
acwing753:输入整数 NN,输出一个 NN 阶的回字形二维数组。
数组的最外层为 11,次外层为 22,以此类推。
输入格式
输入包含多行,每行包含一个整数 NN。
当输入行为 N=0N=0 时,表示输入结束,且该行无需作任何处理。
输出格式
对于每个输入整数 NN,输出一个满足要求的 NN 阶二维数组。
每个数组占 NN 行,每行包含 NN 个用空格隔开的整数。
每个数组输出完毕后,输出一个空行。
数据范围
0≤N≤100
输入样例:
1
2
3
4
5
0
输出样例:
1
1 1
1 1
1 1 1
1 2 1
1 1 1
1 1 1 1
1 2 2 1
1 2 2 1
1 1 1 1
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
这道题也是曼哈顿距离的解法最佳 我们发现外围到内的数依次增大
所以我们设i j分别为行和列 再分别设左右上下边 n为数组大小
left=i+1,right=n-i,up=j+1,down=n-j; 然后再选这到四条边任意一条中距离最短的边的距离
比如第一个点(0,0)到left的距离为1 到right的距离为n 到up的距离为1 到down的距离为n
我们取其中最小的 也就是1 同理 外面一圈都会是1 再往内则依次递增
代码如下(我偷个懒 还是用自己擅长的C++写吧 其实跟C也差不多)
#include<iostream>
using namespace std;
int main(){
int i,j,n;
while(cin>>n,n!=0){ //cin功能跟scanf一样 是输入
for(i=0;i<n;i++){
for(j=0;j<n;j++){
int left=i+1,right=n-i,up=j+1,down=n-j;
printf("%d ",min(min(left,right),min(up,down)));//min函数 返回二者的最小值
//单纯用C得自己写min函数
}
printf("\n");
}
printf("\n");
}
return 0;
}
当然 矩阵可以玩的很花 比如这样的
1
1 2
2 1
1 2 3
2 1 2
3 2 1
1 2 3 4
2 1 2 3
3 2 1 2
4 3 2 1
1 2 3 4 5
2 1 2 3 4
3 2 1 2 3
4 3 2 1 2
5 4 3 2 1
同样的观察规律 对角线相等 沿着对角线依次递增 抬走
#include<iostream>
using namespace std;
int q[100][100];
int main(){
int n,i,j,k;
while(cin>>n,n!=0){
for(i=0;i<n;i++){
q[i][i]=1;//对角线全为1
for(j=i+1,k=2;j<n;j++,k++){
q[i][j]=k;//沿着对角线依次加1 用K计数
q[j][i]=k;
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("%d ",q[i][j]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
或者这样的
1
1 2
2 4
1 2 4
2 4 8
4 8 16
1 2 4 8
2 4 8 16
4 8 16 32
8 16 32 64
1 2 4 8 16
2 4 8 16 32
4 8 16 32 64
8 16 32 64 128
16 32 64 128 256
也是找规律
#include <iostream>
#include <cmath>
using namespace std;
int q[100][100];
int main(){
int i,j,n,k;
while(cin>>n,n){
for(i=0;i<n;i++){
q[i][i]=pow(2,i*2);//对角线都是2的几次方
for(j=i+1,k=j+i;j<n;j++,k++){//依次平方递增
q[i][j]=pow(2,k);
q[j][i]=pow(2,k);
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("%d ",q[i][j]);
}printf("\n");
}
printf("\n");
}
return 0;
}
4.蛇形矩阵(提高题)
输入两个整数 nn 和 mm,输出一个 nn 行 mm 列的矩阵,将数字 11 到 n×mn×m 按照回字蛇形填充至矩阵中。
具体矩阵形式可参考样例。
输入格式
输入共一行,包含两个整数 nn 和 mm。
输出格式
输出满足要求的矩阵。
矩阵占 nn 行,每行包含 mm 个空格隔开的整数。
数据范围
1≤n,m≤100
输入样例:
3 3
输出样例:
1 2 3 8 9 4 7 6 5
这好像是我们老师讲过的哪一年的期末题?
这道题的规律就像一条蛇一样往里面盘 所以 我们就要用代码教它走路
我们用两个二维数组确定每次走的方向
也可以叫它偏移量 int dx[]={0,1,0,-1}; int dy[]={1,0,-1,0};
然后每次走还要判断是不是碰到了边界m,n或者走到自己走过的路了 不然你这蛇不就乱飞了
感觉语言匮乏 还是看代码更清晰一点吧 配着注释应该能更好理解
#include<iostream>
using namespace std;
int q[100][100];
int main(){
int n,m;
cin>>n>>m;
int dx[]={0,1,0,-1}; int dy[]={1,0,-1,0};
for(int x = 0,y=0,d=0,k=1; k<=n*m;k++){
q[x][y] = k;//k计数 此次递增
int a = x+dx[d], b=y+dy[d];//初始位置0,0
if(a<0 || a>=n ||b<0 ||b>=m ||q[a][b] ){//判断边界
d=(d+1)%4;//转方向 依次右下左上
a=x+dx[d],b=y+dy[d];//加上偏移量
}
x=a,y=b;
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
printf("%d ",q[i][j]);
}
printf("\n");
}
return 0;
}
未完待续 看看以后还有没有什么有趣的矩形题目