1050 螺旋矩阵

该文描述了一个编程问题,涉及构建非递减螺旋矩阵。给定正整数N和一组数字,目标是按照顺时针螺旋顺序填充一个m行n列的矩阵,其中m*n=N,且m>=n。文章提供了思路分析、错误检查和代码实现,包括如何确定矩阵大小、填充规则以及方向判断。
摘要由CSDN通过智能技术生成

1050 螺旋矩阵

分数 25
作者 CHEN, Yue
单位 浙江大学

本题要求将给定的 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,首先N一定要整除i,然后再判断差cha是否最小,我用的方法是如果cha 大于 m - n 则把 m - n赋给cha,这里我是直接比较cha 和 N/i - i 。要注意m - n >= 0;
  2. 我设置了两个矩阵,luo代表螺旋矩阵,label代表每个位置的性质,1是已经有数了,不能再加了,0是还空着,还可以再加。flag代表方向的,如果%4为0就是向右,为1就是向下,为2就是向左,为3就是向右。
  3. 接下来就是以螺旋的方式赋值到luo[][]里,由于是顺时针,向右向下向左向上的顺序。 i,j代表数组的行列。向右j++,向下i++,向左j–,向上i–。
  4. 同时判断能不能再向前走了,两种情况。1是不能超出矩阵行列2是前方有没有数字,如果已经有了(label为1),则flag++,该改变方向了。

错误分析

  • m - n >= 0别忘了等于号。

代码实现

#include<stdio.h>
#include<stdlib.h>
int cmp(const void * a, const void * b){
	int *pa = (int *)a;
	int *pb = (int *)b;
	int numa = *pa;
	int numb = *pb;
	return numb - numa; 
}

int main(){
	int N;
	scanf("%d",&N);
	int a[N];
	
	for(int i = 0; i < N; i++){
		scanf("%d",&a[i]);
	}
	qsort(a,N,sizeof(int),cmp);//最高位放在0号位 
	int cha = N;//
	int m = 0;
	int n = 0;
	for(int i = 1;i <= N; i++){
		if(N % i == 0){
			if(cha > N / i - i && N / i - i >= 0){
				cha = N / i - i;
				m = N / i;
				n = i; 
			}
			
		}
	} 
	int luo[m][n]; 
	int label[m][n];
	for(int i = 0; i < m; i++){
		for(int j = 0; j < n; j++){
			label[i][j] = 0;
		}
	}
	int flag = 0;
	int i = 0;//螺旋矩阵的行列 
	int j = 0;
	for(int index = 0; index < N; index++){
		luo[i][j] = a[index];
		label[i][j] = 1;
//		j++;
		if(flag % 4 == 0){
			j++;
			if(j == n - 1 || label[i][j + 1] == 1){
				flag++;
			}
			continue;
		}
		if(flag % 4 == 1){
			i++;
			if(i == m - 1||label[i + 1][j] == 1){
				flag++;
			}
			continue;
		}
		if(flag % 4 == 2){
			j--;
			if(j == 0 || label[i][j-1] == 1){
				flag++;
			}
			continue;
		}
		if(flag % 4 == 3){
			i--;//向上
			if(i==0 || label[i - 1][j] == 1){
				flag++;
			} 
			continue;
		}
		
	}
	for(int i = 0; i < m; i ++){
		for(int j = 0; j < n; j++){
			if(j > 0){
				printf(" ");
			} 
			printf("%d",luo[i][j]); 
		}
		printf("\n");
	}
	return 0; 
}

其他做法参考

PAT乙级1050:螺旋矩阵 (25)
【PAT (Basic Level) Practice】——【快乐模拟】1050 螺旋矩阵

分析

第一

首先对于m,n他们有不同的算法,我认为更好
求n,m 关键在于i*i>=N,如果<N,那么m肯定不是i

    for(int i = 1;i<=N;i++)
    {
        if(i * i >= N && N % i == 0)
        {
            m = i;
            break;
        }
    }
    n = N / m;

第二

求螺旋矩阵,针对的是圈数,如果m是偶数层数就是m / 2 ,如果是奇数还要加1

【解释】
例如 i = 01。
c - 1 - i;//右数第i+1列
r - 2 - i;//倒数第i+2行
int circle = m/2 + m%2;
for (i=0;i<circle;i++)//圈数
//r和c是行列k是个数
    {
        for (j=i;j<(c-i) && k<N;j++)//上面的行,从左边到右边,列变行不变
            b[i][j] = a[k++];
        for (j=i+1;j<(r-i) && k<N;j++)//右边的列,从上面到下面,行变列不变
            b[j][c-1-i] = a[k++];
        for (j=c-2-i;j>=i && k<N;j--)//下面的行,从右边到左边,列变行不变
            b[r-1-i][j] = a[k++];
        for (j=r-2-i;j>i && k<N;j--)//左边的列,从下面到上面,行变列不变
            b[j][i] = a[k++];
    }

不太好理解
往右往下指标都是增加的,往左往上指标都是减少的。
j是充当变化的量,有时候在第一个位置有时候第二个位置。
例如当第一轮第一行完事,j到行那里,从i+1开始不断增加。而列指标c-1-i则是表示最右列不变。
第三个for行就不能变了,j回到列,从右数第二个开始减少,第四个for类似。
要注意第四个for的j不能等于i。
第二轮同理,j = i 从第二行开始,再从右2列开始,再从倒数第二行开始,再从左2列开始等等等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值