PAT 乙级 1050 螺旋矩阵

本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N;m≥n;且 m−n 取所有可能值中的最小值。

输入格式:

输入在第 1 行中给出一个正整数 N,第 2 行给出 N 个待填充的正整数。所有数字不超过 10​4​​,相邻数字以空格分隔。

输出格式:

输出螺旋矩阵。每行 n 个数字,共 m 行。相邻数字以 1 个空格分隔,行末不得有多余空格。

输入样例:

12
37 76 20 98 76 42 53 95 60 81 58 93

输出样例:

98 95 93
42 37 81
53 20 76
58 60 76

原题遇见过三次了。对于这类矩阵输出的题目,先理解层数的概念,比如题目给的案例矩阵,可以将其分为2层,对元素进行填入。用一个变量记作level,level从1开始向上增加到最大值。最大值的确定通过寻找规律可得。最大值与列数目有着一定的规律,列数目n=1,level=1,n=2,level=1,n=3,level=2,n=4,level=2。由此可以得出规律,层数的最大值是列数除以2向上取整。确定层数目的最大值(n+1)/2后,将进行 (n+1)/2次循环,每次循环填上一层数字。

在本题中,以本题提供的矩阵作为例子进行写程序,level等于1时,需要打出最外侧第一层的数字,第1行第1列的元素先被填写一直到第n列,再向下输入到m-1行为止。接着从m行n列向左写一直到第m行第1列的位置。最后从m-1行第1列至第2行第1列。

将所有的行数改写为层数level,从左往右填写的第n列改写成n+1-level,向下输入到m-level行为止,从m行n列需要更改为m+1-level行n+1-level列至m+1-level行level列,最后从m-level到level+1行为止,列数仍为第level列。

第一次有三个测试点没有过,先输了一个特殊情况,5个元素的数组1[1,2,3,4,5]。结果却是5行一列的[5,0,0,0,1],感觉上像是最后一步从下往上输的时候控制下标的count大于N,所以导致数字被写为0了。对此,加上控制条件。

第二个测试点输入了一个案例3*3的矩阵[1,2,3,4,5,6,7,8,9]结果却显示最后出现了而且在第2层第1个元素即最中间的元素1变为了0》由此修改第一步往右输的语句,使得count>=N时结束。

第三个没过的测试点一直显示段错误,先将二维数组调大没有用,过大就超时,这里没有认识到可以用下二维指针控制动态数组,修改后通过结果。

代码如下:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

int a[10000];

bool compare(int a,int b)
{
    return a>b;
}

int main()
{
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(0);
    int N;
    cin>>N;
    int m,n;
    for(n=(int)sqrt(N);n>=1;n--)
    {
        if(N%n==0)
        {
            m=N/n;
            break;
        }
    }
    int **b=new int*[m+1];
    //设立一个动态二维数组来存放
    for(int i=0;i<=m;i++)
    {
        b[i]=new int[n+1];
    }

    for(int i=1;i<=N;i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+N+1,compare);
    int level;
    int count=1;
    for(level=1;level<=(n+1)/2;level++)
    {
        for(int i=level;i<=n+1-level;i++)
        {
            if(count>=N)
            {
                break;
            }
            b[level][i]=a[count];
            count++;
        }
        for(int i=level+1;i<=m-level;i++)
        {
            b[i][n-level+1]=a[count];
            count++;
        }
        for(int i=n+1-level;i>=level;i--)
        {
            b[m+1-level][i]=a[count];
            count++;
        }
        for(int i=m-level;i>=level+1;i--)
        {
            if(count>=N)
            {
                break;
            }
            b[i][level]=a[count];
            count++;
        }
    }
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(j<=n-1)
            {
                cout<<b[i][j]<<" ";
            }
            else if(j==n)
            {
                cout<<b[i][j]<<endl;
            }
        }
    }
    for(int i=0;i<=m;i++)
    {
        delete[]b[i];
    }
    delete[]b;
    return 0;
}
//矩阵大小为n列,m行,此处m=4,n=3
//每一层的元素个数 2n+2m-8level+4,level=1,2,..

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值