ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-01-28 19:01:45  阅读:189  来源: 互联网

标签:cnt Pat Matrix -- res Spiral while ++ int


文章目录


前言

今天练习了一下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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有