其他分享
首页 > 其他分享> > Pat-甲-1105(Spiral Matrix -螺旋矩阵)

Pat-甲-1105(Spiral Matrix -螺旋矩阵)

作者:互联网

文章目录


前言

今天练习了一下Pat1105题,第一眼看着有点奇怪,主要是spiral这个单词一时间忘记了有点尴尬,根据样例发现就是一道模拟题,虽然模拟题一般挺简单的,但是对于我好像,比一般算法题错还容易错。。


提示:以下是本篇文章正文内容,下面案例可供参考

题目

1105 Spiral Matrix (25 分)
This time your job is to fill a sequence of N positive integers into a spiral matrix in non-increasing order. A spiral matrix is filled in from the first element at the upper-left corner, then move in a clockwise spiral. The matrix has m rows and n columns, where m and n satisfy the following: m×n must be equal to N; m≥n; and m−n is the minimum of all the possible values.

Input Specification:

Each input file contains one test case. For each case, the first line
gives a positive integer N. Then the next line contains N positive
integers to be filled into the spiral matrix. All the numbers are no
more than 10 4 . The numbers in a line are separated by spaces.

Output Specification:

For each test case, output the resulting matrix in m lines, each
contains n numbers. There must be exactly 1 space between two adjacent
numbers, and no extra space at the end of each line.

Sample Input:

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

Sample Output:
98 95 93
42 37 81
53 20 76
58 60 76

二、解法

本题要求螺旋式按照输入数组从大到小输出一个m x n 的矩阵,要求矩阵m - n 要最小,很简单想到求因式分解,求其差值最小,很简单就是从给定X的开平方项递减循环。

for(int i = sqrt(x); i >0 ; i--){
		//当第一次x % 1==0 时则得到差值最小的因式分解
        if(x % i == 0){
            m = x / i;
            n = i;
            break;
        }
    }
    //m为行, n为列

然后要求数组从大到小输出,那么就需要对输入的数组进行排序,直接用stl 的快排就行了。

// 注意sort 默认时从小到大, 可以自定义个比较器改一下,这里仍使用默认,后面会解释
sort(q,  q + x);

在数组排序后,将数组螺旋输出为m x n 的矩阵,其实只要按照从左 -> 右 -> 下 -> 上 按一个循环去给矩阵赋值,同时由于从外向内循环,所以需要不断更新左右上下的边界(建议画一个图模拟一下矩阵i,j坐标的变化,很快就能找到边界变化规律)

int up = 0, down = m - 1, left = 0, right = n -1;
    int i = 0, j = 0;
    //由于我采用的是sort的默认排序,所以排序后是从小到大的,则对螺旋矩阵赋值时要从后往前扶赋值到矩阵,cnt = x -1(最大值开始)
    int cnt = x - 1;
    while( cnt >= 0 ){
    	//不取j <= right 这样可以保证同一循环内的各方向的更新次数是相同的,边界管理更加简单一些。
        while( j < right && cnt >= 0){
            res[i][j++] = q[cnt--]; 
        }
        while( i < down && cnt >= 0){
            res[i++][j] = q[cnt--];
        }
        while( j > left && cnt>= 0){
            res[i][j--] = q[cnt--];
        }
        while( i> up && cnt >= 0){
            res[i--][j] = q[cnt--];
        }
        //边界的更新最好画一个图用样例模拟一次就好理解了
        right --;
        down --;
        left ++;
        up ++;
        i++,j++;
        //当cnt == 0 的直接操作,不进入下一循环,避免下一循环特殊情况可能存在的问题,因为去除此代码,测试点2过不去
        if( cnt == 0){
            res[i][j] = q[cnt--];
        }
    }

最后有一个小坑,就是需要对 N = 1的情况要单独处理,否则测试点4会过不去。

    if(x == 1){
        printf("%d", q[0]);
        return 0;
    }

AC答案

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int x , m , n;
int main(){
    scanf("%d", &x);
    int q[x];
    for(int i = 0; i< x; i++){
        scanf("%d", &q[i]);
    }
    if(x == 1){
        printf("%d", q[0]);
        return 0;
    }
    for(int i = sqrt(x); i >0 ; i--){
        if(x % i == 0){
            m = x / i;
            n = i;
            break;
        }
    }
    int res[m][n];
    sort(q, q + x);
    int up = 0, down = m - 1, left = 0, right = n -1;
    int i = 0, j = 0;
    int cnt = x - 1;
    while( cnt >= 0 ){
        while( j < right && cnt >= 0){
            res[i][j++] = q[cnt--]; 
        }
        while( i < down && cnt >= 0){
            res[i++][j] = q[cnt--];
        }
        while( j > left && cnt>= 0){
            res[i][j--] = q[cnt--];
        }
        while( i> up && cnt >= 0){
            res[i--][j] = q[cnt--];
        }
        right --;
        down --;
        left ++;
        up ++;
        i++,j++;
        if( cnt == 0){
            res[i][j] = q[cnt--];
        }
    }
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            if(j == 0){
                printf("%d",res[i][j]);
            }else{
                printf(" %d",res[i][j]);
            }
        }
        puts("");
    }

    return 0;
}

总结

模拟题本身不难,一般情况下按照样例画出图模拟一遍就可以知道一般思路,注意点就是要小心特殊情况(比如 N = 1 等等)。加油吧!

标签:cnt,Pat,Matrix,--,res,Spiral,while,++,int
来源: https://blog.csdn.net/qq_45385022/article/details/122734948