【全网最细PAT题解】【PAT乙】1050 螺旋矩阵

70 篇文章 0 订阅
该文章描述了一种将给定正整数序列按非递减顺序填充到螺旋矩阵中的方法。首先计算出最接近正方形的矩阵尺寸,然后通过循环按层填充二维数组,最后按顺序输出矩阵。解题思路包括寻找矩阵尺寸、排序输入数字以及按螺旋顺序填充和输出。
摘要由CSDN通过智能技术生成

题目链接

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

题目大意

给出你一串数,让你按照尽可能接近正方形的矩形来对数字按照从大到小在矩阵中顺时针输出

解题思路

本题看起来很麻烦,其实思路比较常规,需要注意一下几点

  • 首先就是尽可能接近正方形,这里是从数字个数N直接开根号开始向0循环,这样第一个得到的可行值就是最接近正方形的矩形
	for(int i=sqrt(N);i>=0;i--){
        //因为要 m−n 取所有可能值中的最小值,所以直接从开根号开始向0判断
        if(N%i==0){
            n=i;
            m=N/n;
            break;
        }
    }
  • 然后就是输出问题,采取的办法是先将数据存储到二维数组中,然后输出二维数组,而不是直接按照矩形的方式直接输出,个人感觉这种方法比较直观更适合读者理解
  • 然后就是注意怎么保存到二维数组中,其实看起来很麻烦,仔细想就会发现其实判断怎么保存是比较容易的

题解

#include<bits/stdc++.h>
using namespace std;

bool cmp(int a,int b){
    return a>b;
}
int main(){
    int N;
    cin>>N;
    vector<int> v(N);
    int t=0;        //是用来判断已经把几个数字放到了规定位置
    for(int i=0;i<N;i++){
        cin>>v[i];
    }
    sort(v.begin(),v.end(),cmp);
    int mmin=1000000;
    int m,n;
    for(int i=sqrt(N);i>=0;i--){
        //因为要 m−n 取所有可能值中的最小值,所以直接从开根号开始向0判断
        if(N%i==0){
            n=i;
            m=N/n;
            break;
        }
    }

    //采取不直接输出,而是先对对应的二维数组赋值以后按顺序输出
    vector<vector<int>> g(m,vector<int>(n));		//m行n列的二维数组
    int level = m/2+m%2;	//m行,当行为奇数时层数为m/2+1,为奇数时为m/2'
    for(int i=0;i<level;i++){			//按层数循环
        for(int j=i;j<=n-1-i&&t<N;j++)			//按行填充
            g[i][j]=v[t++];
        for(int j=i+1;j<=m-2-i&&t<N;j++)        //填充列
            g[j][n-1-i]=v[t++];
        for(int j=n-i-1;j>=i&&t<N;j--)          //反向填充行
            g[m-1-i][j]=v[t++];
        for(int j=m-2-i;j>=i+1&&t<N;j--)        //反向填充列
            g[j][i]=v[t++];
    }
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            printf("%d",g[i][j]);
            if(j!=n-1)	printf(" ");
        }
        cout<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值