蓝桥杯练习——回形取数

题目描述

回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。

输入

输入第一行是两个不超过200的正整数m,  n,表示矩阵的行和列。接下来m行每行n个整数,表示这个矩阵。

输出

输出只有一行,共mn个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。

样例输入

3  3 

1  2  3 

4  5  6 

7  8  9 

样例输出

1 4 7 8 9 6 3 2 5

 

这道题其实就是一个找规律的题,找好规律后几个循环就可以完成输出。

如上图所示,m为行数,n为列数,以一个m=5,n=5的5*5的矩阵为例,先忽略数字,把每一个数字当作矩阵中的一个点,由题意可知输出顺序是从外圈到内圈的逆时针顺序。以最外圈为例,其输出为从(0,0)到(m-1,0)的红色点,然后是橙色点,然后是黄色,最后是绿色,按照逆时针的顺序,外圈输出完毕。

如上图所示为第二圈,就是以(1,1)为起始点的圈,其顺序依旧是红、橙、黄、绿,第二圈输出完毕,最后是内圈(2,2),只有一个点,直接输出。这样,一个矩阵就输出完毕。

不难发现其中的输出规律,每次输出按圈逆时针输出,从外圈到内圈,起始点为(0,0),(1,1,),(2,2)。也就是说,每次只要找到起始点,然后按照顺序进行红、橙、黄、绿四次输出就可以了。

假设每次的起始点为(x,x)

红色的点为:(x,x)到(m-1-x,x)                                     x坐标依次加1

橙色的点为:(m-1-x,x+1)到(m-1-x,n-1-x)                    y坐标依次加1

黄色的点为:(m-2-x,n-1-x)到(x,n-1-x)                         x坐标依次减1

绿色的点为:(x,n-2-x)到(m-1-x,x+1)                            y坐标依次减1

通过以上的规律,每次更换不同的起始点,通过四个for循环依次输出红、橙、黄、绿点,直至全部输完。

起始点就是每一圈的第一个点,想要找到起始点首选要知道圈数。

全是应该是(min(m,n)+1)/2  ,即行、列中最小数加一除2,除数是取整,由此可得圈数l,起始点则是(0,0)到(l-1,l-1)

第一个循环是起始点循环,然后每个起始点控制的输出再通过四个方向循环输出。

 

有两种特殊情况需要注意

1、m<n,且m为单数

这种情况在输出完外圈后,内圈只有一个从左到右的横向输出。

 

2、n<m,n为单数

这种情况在输出完外圈后,内圈只有一个从上到下的纵向输出

 

因此在四个方向输出前要判断是否是最内圈,且最内圈是否满足以上两种情况,如果满足则直接横向或者纵向输出,如果不满足再进行四个方向的输出。

 

代码:

#include<stdio.h>
int main()
{
    int m,n;
    scanf("%d%d",&m,&n);   //输入行数和列数 
    int a[m][n];
    int min=m<n?m:n;
    int len=(min+1)/2;
    for(int i=0;i<m;i++)     //输入矩阵中的数字 
    {
        for(int j=0;j<n;j++)
        {
            scanf("%d",&a[i][j]);
        }
    }

    for(int x=0;x<len;x++)         //按照起始点依次按圈逆时针输出 
    {
        if(x==len-1&&((min+1)%2)==0)    //如果是最内圈 
        {
            if(m<n)                //这种情况是横向输出 
            {
                for(int i=x;i<n-x;i++)
                {
                   printf("%d ",a[x][i]);
                   }
                
            }
            else                      //纵向输出 
            {
                for(int i=x;i<m-x;i++)
                {
                   printf("%d ",a[i][x]);
                }
                
            }
        }
        else
       {
    
               for(int i=x;i<m-x;i++)   //红色的点 
            {
               printf("%d ",a[i][x]);
            }
    
            for(int i=x+1;i<n-x;i++)    //橙色的点 
            {
                printf("%d ",a[m-1-x][i]);
            }
    
            for(int i=m-2-x;i>=x;i--)    //黄色的点 
             {
                printf("%d ",a[i][n-1-x]);
            }
    
            for(int i=n-2-x;i>x;i--)     //绿色的点 
            {
                printf("%d ",a[x][i]);
            }
    
        }
    }
    return 0;
 } 

  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值