PAT1050

本文介绍了一种算法,该算法能够将一系列正整数按非递增顺序填充到螺旋矩阵中。螺旋矩阵是从左上角开始按顺时针螺旋方向填充的矩阵。文章详细解释了如何确定矩阵的尺寸,并提供了完整的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

#include<iostream>
#include<vector>
#include<algorithm>
#include <math.h> 
using namespace std;

int main() {

    int N;
    cin >> N;
    vector<int> A(N);
    for (int i = 0;i<N;i++)
        cin >> A[i];
    //当只输入一个数时直接输出
    if (N == 1)
    {
        cout << A[0] << endl;
        return 0;
    }
    sort(A.begin(), A.end());
    int a=sqrt(N);
    while (N % a != 0) --a;
    int c= N / a;
    int m = c, n = a;
    vector< vector<int> > B(m, vector<int>(n, 0));  

    int direct[] = { 0,1,2,3 }, d = 0, posD = 0;    //控制方向:向右,向下,向左,向上。  
    int x = 0, y = 0, posA = N-1;

    while (posA>=0)
    {
        if ((x == m || x<0) || (y == n || y<0)|| B[x][y] != 0)//方向调转,碰到边界或者下一个数已经  
        {              
            ++posD;
            switch (d)       //之前已经超过边界一格了,所以要回退一步。  
            {
            case 0: y--;x++;break;
            case 1:x--;y--;break;
            case 2:y++;x--;break;
            case 3: x++;y++;break;
            }
            d = direct[posD % 4];
        }
        B[x][y] = A[posA];--posA; //往二维数组填充数据。  
        switch (d)   //一直往上面设定的方向行走和填充。  
        {
        case 0: y++;break;
        case 1:x++;break;
        case 2:y--;break;
        case 3: x--;break;
        }
    }

    for (int h = 0;h<m;h++) //打印结果  
    {
        for (int l = 0;l<n;l++)
        {
            cout << B[h][l];
            if (l != n - 1)
            {
                cout << " ";
            }
        }
        cout << endl;
    }
    return 0;
}
  1. 开根号定义在math.h
  2. 当N=11*21时,开根号后得到的数一定位于m和n之间。通过递减直到余数为0
  3. 通过vector构造二维数组。
  4. 在判断是否需要调整方向时,是3个或。注意只要前面有条件为真,就不再进行后面的判断。(参考的做法使用的是内置数组,可以向前(下标为-1)越界访问,但是vector不行。所以改进将判断内容是否为0放在最后)
  5. 判断内容是否为0用于数组内层的迭代;判断x和y是否越界用于外层循环
  6. 通过dircted数组决定方向。大大减少了编程的复杂程度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值