PAT 1050 螺旋矩阵

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

输入格式:

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

输出格式:

输出螺旋矩阵。每行 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

解题思路:

1、要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N;m≥n;且 m−n 取所有可能值中的最小值。

容易看出m、n位于√N两边(m>=n,m位于√N右边,n位于√N左边,或m=n=√N);要使得m-n的值最小,可以想到找到
i∈[√N,N]内第一个满足N%i=0。
scanf("%d",&N);
for(int i=ceil(sqrt(1.0*N));i<=N;i++){
    if(N%i==0){
        n2=i;
        break;
    }
}
n1=N/n2;

2、从左上角第 1 个格子开始,按顺时针螺旋方向填充矩阵。

我这里借用了DFS的思想,做了一些改变。顶点的值x、y为要填充的二维矩阵,每次从四个方向(按右、下、左、上顺序)一
一直走到底。
void DFS(int i,int j){
	    for(int k=0;k<4;k++){
	        int newX=i+X[k];
	        int newY=j+Y[k];
	        if(iscan(newX,newY)&&!hashTable[newX][newY]){
	        	//k:0 右 1 下 2 左 3 上 沿着一个方向一路走直到走到边界或者已被访问的顶点。
	            while(iscan(newX,newY)&&!hashTable[newX][newY]){
	                  hashTable[newX][newY]=true;//记录已经访问
	                  res[newX][newY]=vt[_index++];//写入二维矩阵
	                  newX+=X[k];
	                  newY+=Y[k];
	            }
	            newX-=X[k];//复位X
	            newY-=Y[k];//复位Y
	            DFS(newX,newY);
	
	        }
	    }
}

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <math.h>
using namespace std;
int N,x,n1,n2;
int X[4]={0,1,0,-1};
int Y[4]={1,0,-1,0};
vector<int> vt;
vector<vector<bool> > hashTable;
vector<vector<int> >res;
bool iscan(int i,int j){
    bool flag=true;
    if(i<0||j<0||i>=n2||j>=n1)
        flag=false;
    return flag;
}
bool cmp(int a,int b){
    return a>b;
}
void show(){
    for(int i=0;i<n2;i++){
        for(int j=0;j<n1;j++){
            printf("%d",res[i][j]);
            if(j!=n1-1)
                printf(" ");
        }
        printf("\n");

    }
}
int index=0;
void DFS(int i,int j){
    for(int k=0;k<4;k++){
        int newX=i+X[k];
        int newY=j+Y[k];
        if(iscan(newX,newY)&&!hashTable[newX][newY]){
            while(iscan(newX,newY)&&!hashTable[newX][newY]){
                  hashTable[newX][newY]=true;
                  res[newX][newY]=vt[index++];
                  newX+=X[k];
                  newY+=Y[k];
            }
            newX-=X[k];
            newY-=Y[k];
            DFS(newX,newY);

        }
    }
}
int main(){
    scanf("%d",&N);
    for(int i=ceil(sqrt(1.0*N));i<=N;i++){
        if(N%i==0){
            n2=i;
            break;
        }
    }
    n1=N/n2;
    for(int i=0;i<N;i++){
        scanf("%d",&x);
        vt.push_back(x);
    }
    sort(vt.begin(),vt.end(),cmp);
    for(int i=0;i<n2;i++){
        vector<bool> temp1;
        vector<int> temp2;
        for(int j=0;j<n1;j++){
            temp1.push_back(false);
            temp2.push_back(0);
        }
        hashTable.push_back(temp1);
        res.push_back(temp2);
    }
    DFS(0,-1);
    show();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值