PAT (Basic Level) Practice 1050 螺旋矩阵

乙级1050
在这里插入图片描述
第一次看到时间限制200ms以为是找规律,找了半天没找到,后来才觉得这应该是模拟题,模拟题意将数字“螺旋式”填充进去

1.m x n的确定
遍历找最大公约数
如果是i~N遍历的话 循环到最后出来的值必然是m,然后N/m出来的就是n,并且m必然>n,举个栗子 就像11质数,遍历到最后i=N,那么这时候m=i,必然最大
还有个剪枝的好方法,这题不会在这上面刁难人的,所以怎么做都行:
循环for(int i = 1; i*i<=N;i++)这里用i*i<=N就是寻找前半边即可,这样剩下部分在i之后的值必然大于i,也就是先确定n,再计算出m

2.螺旋模拟
螺旋分四个方向,右、下、左、上
所以可以对四个反向直接模拟,一圈结束之后,在新的起点再来一圈,直到数字用完
每一圈要确定好方向,并且到一个位置要留意是不是到了边界,如果到了边界就表示要换方向了
所以将矩阵四个角的点的坐标记录下来为p1,p2,p3,p4,这四个点就是是否到边界的标准,比如向右,就要留意x轴上的值不能超过p2的x值,如果相等,那就表示下一步就要换方向了,而且肯定是向下,以此类推。
值得注意的是,最后向上边界并不是在p1点上,而是即将到p1点的时候就要停止换方向,设动点为p,那么就是p.y+1 == p1.y;此时就要开始新的一圈
对于新的一圈,之前设的端点要全往里缩一圈,就是第二圈矩阵了
AC代码:

#include<bits/stdc++.h>
using namespace std;
struct coordinate{
	int x;
	int y;
};
coordinate p1,p2,p3,p4,p;
bool comp(int a,int b){
	if(a>b)	return true;
	return false;
}
int main(){
	int N;
	cin>>N;
	int *a = new int[N];
	int m,n; //行,列 
	for(int i = 1; i*i<=N;i++){
		if(N%i==0){
			n = i;
			m = N/i;
		} 
	}
	int martix[m][n];
	for(int i = 0;i<N;i++){
		scanf("%d",&a[i]);
	} 
	sort(a,a+N,comp);
	p1.x = 0,p1.y = 0;
	p2.x = n-1,p2.y = 0;
	p3.x = n-1,p3.y = m-1;
	p4.x = 0,p4.y = m-1;
	p.x = 0,p.y = 0;
	int left=1,down=0,right=0,up=0;
	for(int i = 0;i<N;i++){
		martix[p.y][p.x] = a[i];
//		printf("m[%d][%d] = %d   a[%d] = %d\n",p.y,p.x,martix[p.y][p.x],i,a[i]);
		if(left){
			if(p.x+1>p2.x){
				p.y++;
				left = 0;down = 1;
			}else{
				p.x++;
			}
		}
		else if(down){
			if(p.y+1>p3.y){
				p.x--;
				down = 0;right = 1;
			}else{
				p.y++;
			}
		}
		else if(right){
			if(p.x-1<p4.x){
				p.y--;
				right = 0;up = 1;
			}else{
				p.x--;
			}
		}
		else if(up){
			if(p.y-1==p1.y){//顶到头的时候注意这地方代码有点不一样 
				p.x++;
				up = 0;left = 1;
				p1.x++,p1.y++;
				p2.x--,p2.y++;
				p3.x--,p3.y--;
				p4.x++,p4.y--;
			}else{
				p.y--;
			}
		}
	}
	for(int i = 0;i<m;i++){
		int isfirst = 1;
		for(int j = 0;j<n;j++){
			if(isfirst){
				printf("%d",martix[i][j]);
				isfirst = 0;
			}else	printf(" %d",martix[i][j]);
		}
		printf("\n");
	}
	return 0;
}

百度了一下其它方式,基本大同小异。
因为我对算法复杂度并不是特别熟悉,所以在模拟的地方选择了复杂度O(n)的操作,好像好多人都是外层1个循环+内层4个循环,直接循环四个方向,再缩进

猜你喜欢

转载自blog.csdn.net/a656418zz/article/details/84637450
今日推荐