牛客刷题(矩阵加圣诞树)

目录

一.两个矩阵

1.回型矩阵

 2.蛇形矩阵

二.两个圣诞树

1.普通圣诞树

2.超级圣诞树


一.两个矩阵

1.回型矩阵

描述:给你一个整数n,按要求输出n∗n的回型矩阵。
输入描述:输入一行,包含一个整数n,1<=n<=19。
输出描述:输出n行,每行包含n个正整数。

例如:
输入:4

输出:
1    2   3   4
12 13 14  5
11 16 15  6
10   9   8   7

这道题目,其实不难,观察我们可以发现

 它是一圈一次循环,也就是说,我们只要写完一圈的代码,然后循环即可。不过还是要注意点细节。

#include<stdio.h>
int main()
{
    int n,i,j;
    int arr[20][20]={0};
    scanf("%d",&n);
    int out=1;
    int x=0;
    int y=n-1;
    while(out<=n*n)
    {
        for(i=x;i<=y;i++)
            arr[x][i]=out++;
        for(i=x+1;i<=y;i++)
            arr[i][y]=out++;
        for(i=y-1;i>=x;i--)
            arr[y][i]=out++;
        for(i=y-1;i>x;i--)
            arr[i][x]=out++;
        x++;
        y--;
    }
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }
   
    return 0;
}

对于循环体内的代码端注意要把定量转换为变量。因为它是在不断变换之中的。

结果:

 2.蛇形矩阵

描述:给你一个整数n,输出n∗n的蛇形矩阵。
输入描述:输入一行,包含一个整数n
输出描述:输出n行,每行包含n个正整数,通过空格分隔。1<=n<=1000

例如:
输入:
4
输出:
1 2 6 7
3 5 8 13
4 9 12 14
10 11 15 16

可以简单画个图分析一下:

 ①.暴力求解

 通过这个图形,可以直观看到二维数组的变换,但是怎么转换成计算机语言还是比较难办的。笔者在初接触这个题目,是通过坐标直接暴力求解的,但是过于繁琐,也不易于调试,代码可读性较差。不过思路很明确。先见图:

 上代码(笔者自己写的比较粗糙,但是万幸跑过去了)虽说比较暴力,但是还是由很多小细节需要注意的。

#include<stdio.h>
int main()
{
    int n,i,j;
    int arr[20][20]={0};
    //找坐标关系
    scanf("%d",&n);
    int out=1;
    int p=1;
    //第一个没必要讨论
    arr[0][0]=out++;
    arr[n-1][n-1]=n*n;
    while(p<n)//此处条件还可以写为p<=2*n-2
    {
        for(i=0;i<=p;i++)
        {
            arr[i][p-i]=out++;
        }
        p++;
        if(p==n)
            break;
        for(i=p;i>=0;i--)
        {
            arr[i][p-i]=out++;
        }
        p++;
    }
    int x=1;
    while(p<2*n-2)
    {
        if(n%2==0)
        {
                for(i=p-x;i>=x;i--)
            {
                arr[i][p-i]=out++;
            }
            p++;
            x++;
            if(p==2*n-2)
                break;
            for(i=x;i<=p-x;i++)
            {
                arr[i][p-i]=out++;
            }
            p++;
            x++;
        }
         else
         {
             for(i=x;i<=p-x;i++)
            {
                arr[i][p-i]=out++;
            }
            p++;
            x++;
            if(p==2*n-2)
                break;
            for(i=p-x;i>=x;i--)
            {
                arr[i][p-i]=out++;
            }
            p++;
            x++;
         }
    }
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

算是比较low了,写了有70多行。

②.优化算法(大神确实厉害👍)

如果不从坐标,换个角度思考呢?

为了方便我们从(1,1)开始初始化。

通过上述图片:

 我们可以从,移动方向入手,分析发现,它的移动方向只有:

右和右上;

左和左下。

运动情况分为6种:

  1. 碰到上边界(即i等于1 且 j小于n): 列增加1,行不变--------往右移动一格
  2. 碰到左边界(即j等于1 且 i小于n): 行增加1,列不变--------往下移动一格
  3. 碰到右边界(即j等于n): 行增加1,列不变--------往下移动一格
  4. 碰到下边界(即i等于n): 列增加1,行不变--------往右移动一格

上面四种是在边界上行走的方式,下面就是在边界中间的运动情况。

  1. 除去上面四种的边界情况,就是在边界中间的左下移动
  2. 除去上面四种的边界情况,就是在边界中间的右上移动
    #include <stdio.h>
    int array[1001][1001] = { 0 };
    int main(void)
    {
        int n = 0;
        scanf("%d",&n);
        int i = 1, j = 1, k = 0,pos = 1; //pos代表方向移动   1代表右上   -1代表左下
        array[i][j] = 1;
        for (k = 2; k <= n*n; k++)
        {
            if (i == 1 && j <n && pos ==1) //碰到上边界,列增加1,行不变     此后行增,列减
            {
                array[i][++j] = k;
                pos = -1;                 //方向注意
            }
            else if(j==1 && i<n && pos == -1)//碰到左边界,行增加1,列不变     此后行减,列增
            {
                array[++i][j] = k;
                pos = 1;                     //方向注意                
            }
            else if (j == n && pos==1) //碰到左边界,行增加1,列不变     此后行增,列减
            {
                array[++i][j] = k;
                pos = -1;                     //方向注意
            }
            else if (i == n && pos ==-1) //碰到右边界,列增加1,行不变    此后行减,列增
            {
                array[i][++j] = k;
                pos = 1;
            }
            else if (pos == 1)         //除去上面的边界情况,就是中间移动过程
            {
                array[--i][++j] = k;
            }
            else if(pos == -1)
            {
                array[++i][--j] = k;
            }
        }
        for (i = 1; i <= n; i++)
        {
            for (j = 1; j <= n; j++)
                printf("%d ",array[i][j]);
            printf("\n");
        }
        return 0;
    }

    不得不说,这段代码真的行云流水,大神厉害。

    运行结果都是正确的。                                                                                                         

二.两个圣诞树

1.普通圣诞树

描述
今天是圣诞节,牛牛要打印一个漂亮的圣诞树送给想象中的女朋友,请你帮助他实现梦想。
输入描述:输入圣诞树的高度h,1<= h <= 1001<=h<=100
输出描述:输出对应的圣诞树
示例1
输入:
1
输出:
  *  
 * * 
* * *
  *
示例2
输入:
2
输出:
     *     
    * *    
   * * *   
  *     *  
 * *   * * 
* * * * * *
     *
     *
这道题目,比较需要注意的是空格,然后需要选取好对象,先抛去最后的小尾巴,前面我们就可以发现,它的基本最小组成单元:

  *  
 * * 
* * *
  *

以此为基准进行扩张。(补充说明为什么要以此为基本单元,这一点比较细微,笔者也是观察试验了许久才发现,在笔者百思不得敲代码时发现每个小三角形的三行竟然都是一样的,连空格都一样,如果没有这个发现,这道题相当难做):

上代码:

#include<stdio.h>
int main()
{
    //做三个特殊处理即可
    int intm,num,i;
    scanf("%d",&intm);
    num=intm*3;
    //如果进行3*intm次循环实在繁琐,所以进行intm次循环,但是要注意三行处理
    for(i=1;i<=intm;i++)
    {
        //注意归并
        for(int m=1;m<=num-1;m++)
        {
            printf(" ");
        }
        for(int n=1;n<=i;n++)
        {
            printf("*     ");
        }
        printf("\n");
        for(int m=1;m<=num-2;m++)
        {
            printf(" ");
        }
        for(int n=1;n<=i;n++)
        {
            printf("* *   ");
        }
        printf("\n");
        for(int m=1;m<=num-3;m++)
        {
            printf(" ");
        }
        for(int n=1;n<=i;n++)
        {
            printf("* * * ");
        }
        printf("\n");
        num=num-3;
    }
    for(int k=1;k<=intm;k++)
    {
        for(int j=1;j<=(6*intm-1)/2;j++)
        {
            printf(" ");
        }
        printf("*\n");
    }
    
    return 0;
}

可爱的圣诞树🎄:

 友友们不妨尝试一下送给自己的女朋友哦🌹。

2.超级圣诞树

描述
今天是圣诞节,牛牛要打印一个漂亮的圣诞树送给想象中的女朋友,请你帮助他实现梦想。
输入描述:输入圣诞树的大小 n n
1≤n≤81≤n≤8
输出描述:输出对应的圣诞树

输入:1

 输入:2

 输入:3

 输入:4

 这道题目笔者苦思冥想了两个小时也是没有头绪,只是发现每一个圣诞树都是以上一个圣诞树为基准,三个再重新为一个整体。也是求助了大神才得以解决。分享给大家,大神是真的厉害👍。其实也是我思维局限于上个普通圣诞树,一直想着通过打印或者坐标来解决,然而无果。大神的想法是建立一个二维数组,通过数字替换图形,然后循环。其中清空又重建的思维真的厉害。

上代码:

#include<stdio.h>
int main()
{
    int arr[600][800]={{0,0,1,0,0},{0,1,0,1,0},{1,0,1,0,1}};//由0代表' ',1代表'*'
    int n,i,j,k,length=3,width=5;
    scanf("%d",&n);
    //由小得到大
    for(i=2;i<=n;i++)
    {
        //搬运
        for(j=length;j<length*2;j++)
        {
            for(k=0;k<width;k++)
            {
                arr[j][k]=arr[j-length][k];//制作左下角三角形
                arr[j][k+width+1]=arr[j][k];//制作右下角
            }
        }
        //清空原来三角形,清空起初三角形是因为这个三角形不在中央,而在左边,为了放到中间而如此。
        for(j=0;j<length;j++)
        {
            for(k=0;k<width;k++)
            {
                arr[j][k]=0;//清空
            }
        }
        //把三角形放到中央
        for(j=0;j<length;j++)
        {
            for(k=(width+1)/2;k<width+(width+1)/2;k++)
            {
                arr[j][k]=arr[j+length][k-(width+1)/2];
            }
        }
        //变化的数组,需要扩大,以变大后的三角形为新的初始三角形进行变化。当真绝妙。
        length*=2;width=width*2+1;
    }
    for (i = 0; i < length; i++) 
    {//打印圣诞树
        for (j = 0; j < width; j++) 
        {
            if (arr[i][j] == 0) 
            { 
                printf(" "); 
            }
            else 
            { 
                printf("*"); 
            }
        }
        printf("\n");
    }
    for (i = 0; i < n; i++) 
    {//打印树干
        for (j = 0; j < width / 2; j++) 
        { 
            printf(" ");
        }
        printf("*\n");
    }
    return 0;
}

友友们也可以实现送给自己的女朋友哦🌹。这些题目都是牛客网上初阶的题目,较为简单,大家可以点题目就有链接哦。

 

本次分享就到这里,谢谢大家!🌹

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值