PAT乙级1050 螺旋矩阵 测试点1/3/7分析与解决

1050 螺旋矩阵 (25分)

本题要求将给定的 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

本题关键不是螺旋矩阵的实现,而是行数m和列数n的计算,推导如下:
m ∗ n = N , m − n 取 最 小 : n = N / m , 则 转 化 为 m − N / m 取 最 小 , 对 m 求 导 : 1 + N / m 2 m*n=N,m-n取最小:n=N/m,则转化为m-N/m取最小,对m求导:1+N/m^2 mn=Nmnn=N/mmN/mm1+N/m2
可知m-n函数单调递增,于是便可以把m从sqrt(N)-1开始循环寻找m和n,每次循环时赋予n=N/m,直到m*n=N时结束循环。需要注意的是,这样找出的m和n可能会m<n,此时需要交换。
测试点1和3的测试N极有可能是11,或45这样得出的m和n差距较大的数,这样寻找m和n便能解决。

螺旋矩阵的数据填充是每次循环进行一次矩阵外圈的填充,也就是每次循环里面嵌套四个小循环,分别填充这一圈的上、右、下、左。因为m和n值很不确定,所以循环条件为N个数据是否被全部填充到矩阵中。
测试点7的段错误,是循环时数组下标越界造成的,为大循环里面的小循环添加检测数组下标小于N的循环条件便解决啦

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>

using namespace std;

int main() {
    int N;
    cin >> N;
    //如下是计算行列数m和n,解决测试点1和3
    int m = sqrt(N) - 1, n = 1;
    while(m * n != N) {
        m++;
        n = N / m;
    }
    if(m < n) {//可能存在m比n小的情况,需要交换
        int temp = m;
        m = n;
        n = temp;
    }
    int num[N];
    for(int i = 1; i <= N; i++) {
        cin >> num[i - 1];
    }
    sort(num, num + N, greater<int> {});
    int re[m][n];
    int index = 0;//充当提取N个数据的索引,应小于N
    for(int flag = 1; index < N; flag++) {//循环条件为当前索引是否越界
    	//下面四个小循环均要添加索引是否越界这一条件,解决测试点7
        for(int i = flag; i <= n - flag + 1 && index < N; i++) { //上
            re[flag - 1][i - 1] = num[index++];
        }
        for(int i = flag + 1; i <= m - flag + 1 && index < N; i++) { //右
            re[i - 1][n - flag] = num[index++];
        }
        for(int i = n - flag; i >= flag && index < N; i--) { //下
            re[m - flag][i - 1] = num[index++];
        }
        for(int i = m - flag; i >= flag + 1 && index < N; i--) {//左
            re[i - 1][flag - 1] = num[index++];
        }
    }
    for(int a = 1; a <= m; a++) {
        for(int b = 1; b <= n; b++) {
            cout << re[a - 1][b - 1];
            if(b != n) {
                cout << " ";
            }
        }
        cout << endl;
    }
    return 0;
}

螺旋矩阵是我一次Java实验的作业题(计算机实验网课不耽误(lll¬ω¬)),但那个是输入阶数,更像是输出N阶行列式,本题对于在下来说,难点是计算m和n

在下辣鸡大一学生,以上有不正确或不合适的地方望多多包涵O(∩_∩)O
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值