pat 甲级 A1105 Spiral Matrix (25分)

题目链接:

https://pintia.cn/problem-sets/994805342720868352/problems/994805363117768704

 

题目大意:

给出N个正数,将其以非递增填充到一个旋转矩阵Am*n中,从左上角开始,按照顺时针方向,矩阵行列m,n满足:m*n = N,m >= n, 且使得m - n达到最小。

 

思路分析:

根据给出的N,计算出满足要求的矩阵行列数,由于不能用变量作为二维数组的行列下标初始化,故采用vector变长数组的形式。

vector < vector<int> > ans(m, vector<int>(n)); //建一个n*m的数组。即m行,n列。

由于在构造旋转数组的时候,是由外到内,且每层旋转方向同为顺时针,故可记录当前的轮次c,即由外到内的层数,那么我们只要分析一层,然后在外层用一个for循环即可,不难知道,在第c层中,上边的坐标是由[c-1][c-1]~[c-1][n-c](为了理解方便,我们把四边形的顶点归为上一条边),右边的坐标是由[c][n-c]~[m-1][n-c],下边的坐标是由[m-1][n-c-1]~c[m-1][c-1],左边的坐标是由[m-c-1][c-1]~c[c][c-1]。

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

using namespace std;
int N, c, m, n = 1, pos = 0;
bool cmp(int a, int b){
    return a >= b;
}
void calc(int N){ // 计算出满足要求的m,n.
    for(int i = 1; i <= sqrt(1.0*N); i++){
        if(N%i ==0) n = i;
    }
    m = N/n;
}

int main()
{
    cin >> N;
    calc(N);
    vector <int > A(N);
    for(int i = 0; i < N; i++){
        cin >> A[i];
    }
    sort(A.begin(), A.end(), cmp);
    vector < vector<int> > ans(m, vector<int>(n)); //建一个n*m的数组。即m行,n列。
    int i, j;
    for(c = 1; c <= (n+1)/2 ; c++){
        for(j = c - 1; j <= n - c; j++){
            ans[c-1][j] = A[pos++];
        }
        for(i = c; i <= m - c; i++){
            ans[i][n - c] = A[pos++];
        }
        for(j = n - c - 1; j >= c-1; j--){
            ans[m-c][j] = A[pos++];
        }
        for(i = m - c -1; i >= c ; i--){
            ans[i][c-1] = A[pos++];
        }
    }
    for(i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            cout << ans[i][j] ;
            if(j != n - 1) cout << ' ';
        }
        cout << endl;
    }
    return 0;
}

在测试案列通过后,以为提交后会AC,可是,,,

想了很久试了一下案列,当N为质数的时候,比如N=7.得到了下面的输出结果,根据输出结果,判断可能是将数组A越界的元素

赋值给ans,所以分析内层循环后,我们发现在最后一个内层for中,当n=1时,程序会继续执行将第n-2行到第1行的数据覆盖(这里我们从第0行开始计数)。

改进代码,在内层最后一个for循环中,添加一个判断条件,pos < N,即可 AC。

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

using namespace std;
int N, c, m, n = 1, pos = 0;
bool cmp(int a, int b){
    return a >= b;
}
void calc(int N){ // 计算出满足要求的m,n.
    for(int i = 1; i <= sqrt(1.0*N); i++){
        if(N%i ==0) n = i;
    }
    m = N/n;
}

int main()
{
    cin >> N;
    calc(N);
    vector <int > A(N);
    for(int i = 0; i < N; i++){
        cin >> A[i];
    }
    sort(A.begin(), A.end(), cmp);
    vector < vector<int> > ans(m, vector<int>(n)); //建一个n*m的数组。即m行,n列。
    int i, j;
    for(c = 1; c <= (n+1)/2 ; c++){
        for(j = c - 1; j <= n - c; j++){
            ans[c-1][j] = A[pos++];
        }
        for(i = c; i <= m - c; i++){
            ans[i][n - c] = A[pos++];
        }
        for(j = n - c - 1; j >= c-1; j--){
            ans[m-c][j] = A[pos++];
        }
        for(i = m - c -1; i >= c && pos < N ; i--){
            ans[i][c-1] = A[pos++];
        }
    }
    for(i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            cout << ans[i][j] ;
            if(j != n - 1) cout << ' ';
        }
        cout << endl;
    }
    return 0;
}

也可这样。在最后一次循环前添加一个判断n为奇偶的条件。

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

using namespace std;
int N, c, m, n = 1, pos = 0;
bool cmp(int a, int b){
    return a >= b;
}
void calc(int N){ // 计算出满足要求的m,n.
    for(int i = 1; i <= sqrt(1.0*N); i++){
        if(N%i ==0) n = i;
    }
    m = N/n;
}

int main()
{
    cin >> N;
    calc(N);
    vector <int > A(N);
    for(int i = 0; i < N; i++){
        cin >> A[i];
    }
    sort(A.begin(), A.end(), cmp);
    vector < vector<int> > ans(m, vector<int>(n)); //建一个n*m的数组。即m行,n列。
    int i, j;
    for(c = 1; c <= n/2 ; c++){
        for(j = c - 1; j <= n - c; j++){
            ans[c-1][j] = A[pos++];
        }
        for(i = c; i <= m - c; i++){
            ans[i][n - c] = A[pos++];
        }
        for(j = n - c - 1; j >= c-1; j--){
            ans[m-c][j] = A[pos++];
        }
        for(i = m - c -1; i >= c; i--){
            ans[i][c-1] = A[pos++];
        }
    }
    if(n%2){
        for(i = c - 1; i <= m - c; i++){
            ans[i][c-1] = A[pos++];
        }
    }
    for(i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            cout << ans[i][j] ;
            if(j != n - 1) cout << ' ';
        }
        cout << endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值