PAT-B 真题- 1050. 螺旋矩阵

发布于 / PAT-乙级 / 0 条评论

原题干:

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

输入格式:

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

输出格式:

输出螺旋矩阵。每行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的二维vector,然后将数据螺旋这存进去就好了。

这道题的难点在于,螺旋存储的时候必须要特别注意边界,稍不留神就会发生段错误。

这里我的二维vector里面的值全部初始化为0(其实无需特意初始化,因为创建好的vector里面本身就是0,但是我这里为了强调),然后当x或y超越了(0,0,m,n)这个矩阵范围,或者接下来的矩阵元素不是0(说明之前写入过数据,不能覆盖掉),就说明是边界了,需要转换方向了。

具体看代码吧,在这里说不清楚。。。

另外这道题如果使用的不是二维vector而是二维数组会导致内存超限。你也可以用new创建数组,这样和vector的道理是一样的。

下面是代码:

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main() {
    int cnt, m, n, nums[10010] = {0};  //m为行,n为列。
    double tmp = 0.0;
    scanf("%d", &cnt);
    m = sqrt(cnt);
    do{
        tmp = 1.0 * cnt / m;
        n = (int)tmp;
    }while((tmp - n) && m++);  //只要tmp不是整数,就m++并继续。直到m和n正好都是整数,相乘等于cnt 
    if(m>=n) swap(m, n);    //如果m大于n,不符合题意,需要交换m和n
    for(int i = 0; i < cnt; i++)//输入 
        scanf("%d", &nums[i]);
    sort(nums, nums + cnt); //排序。小->大
    vector<vector<int> > result(n ,vector<int>(m, 0)); //存放螺旋矩阵的容器result[n][m],并初始化整个矩阵为0
    int x = 0, y = 0, x_min = 0, y_min = 0, x_max = m - 1, y_max = n - 1;   //x和y为当前的位置。_min和_max为边缘
    int flag = 3;   //方向标志。1->向左,2->向下,3->向右,4->向上
    while(cnt--){
        result[y][x] = nums[cnt];   //添加到容器内
        if((flag == 3 && x == x_max) || (flag == 3 && result[y][x+1]))    //右上角
        flag = 2;   //向下
        else if((flag == 2 && y == y_max) || (flag == 2 && result[y+1][x])) //右下角
        flag = 1;   //向左
        else if((flag == 1 && x == x_min) || (flag == 1 && result[y][x-1])) //左下角
        flag = 4;   //向上
        else if((flag == 4 && y == y_min) || (flag == 4 && result[y-1][x])) //左上角
        flag = 3;   //向右
        if(flag == 1) x--;
        if(flag == 2) y++;
        if(flag == 3) x++;
        if(flag == 4) y--;    //这四行代码用来改变坐标(x,y)
    }
    for(int i = 0; i < n; i++){
        for(int ii = 0 ; ii < m; ii++){
            cout << result[i][ii];
            if(ii != m - 1) cout << ' ';
        }
        cout << endl;
    }
    return 0;
}

转载原创文章请注明,转载自: 斐斐のBlog » PAT-B 真题- 1050. 螺旋矩阵
目前还没有评论,快来抢沙发吧~