打印各种矩阵(上下左右,蛇形,平方.....)

矩阵类题目 可以锻炼循环和数组(特别是二维的)的运用能力 同时还考验做题人的找规律能力和代码实现能力 大部分属于语法题

下面一起来看看都有什么矩阵吧。

预备知识

首先我们得知道二维数组的定义方法

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;
}

未完待续 看看以后还有没有什么有趣的矩形题目

 

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr丶锤子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值