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

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

一.两个矩阵


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


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


1669212116506.jpg


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


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


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


结果:


1669212144076.jpg


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


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


1669212156371.jpg


①.暴力求解


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


1669212165978.jpg


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


#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)开始初始化。


通过上述图片:


1669212187853.jpg


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


右和右上;


左和左下。


运动情况分为6种:


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

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

碰到右边界(即j等于n): 行增加1,列不变--------往下移动一格

碰到下边界(即i等于n): 列增加1,行不变--------往右移动一格

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


除去上面四种的边界情况,就是在边界中间的左下移动

除去上面四种的边界情况,就是在边界中间的右上移动

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


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


1669212201791.jpg


运行结果都是正确的。

相关文章
|
10月前
【动态规划刷题 5】 最小路径和&&地下城游戏
【动态规划刷题 5】 最小路径和&&地下城游戏
|
2月前
|
算法 C语言
每日一题——迷宫问题(I)
每日一题——迷宫问题(I)
|
12月前
|
测试技术 索引 Cloud Native
【刷题日记】120. 三角形最小路径和
本次刷题日记的第 38 篇,力扣题为:120. 三角形最小路径和 ,中等
|
8月前
|
Java
hdu1181 变形课(暴力搜索法)
hdu1181 变形课(暴力搜索法)
31 0
|
12月前
|
数据采集 算法 数据挖掘
【每周一坑】螺旋矩阵
今天这题,看起来挺简单,实际写出来并不容易。在以前公司我曾把它做过招聘的笔试题,结果惨不忍睹,不得不拿掉。
【每周一坑】螺旋矩阵
|
12月前
《蓝桥杯每日一题》递推·AcWing 3777. 砖块
《蓝桥杯每日一题》递推·AcWing 3777. 砖块
57 0
|
Java Python
leetcode每日一题.面试题01.07:旋转矩阵
leetcode每日一题.面试题01.07:旋转矩阵
61 1
|
存储 算法 Java
代码随想录刷题|LeetCode 332.重新安排行程 51. N皇后 37. 解数独
代码随想录刷题|LeetCode 332.重新安排行程 51. N皇后 37. 解数独
代码随想录刷题|LeetCode 332.重新安排行程 51. N皇后 37. 解数独
|
机器学习/深度学习
牛客刷题(矩阵加圣诞树)(下)
牛客刷题(矩阵加圣诞树)
牛客刷题(矩阵加圣诞树)(下)
|
uml
牛客 小乐乐学数学(扫描线+树状数组)
牛客 小乐乐学数学(扫描线+树状数组)
81 0