1105 Spiral Matrix (25 分)

1105 Spiral Matrix (25 分)

题意

给出一组N个数,把这N个数填入一个m*n的螺旋矩阵里。该螺旋矩阵是从外一圈一圈向最中心的数单调不增。第一个数在最外圈左上角。而 m * n = N,m>=n且m与n应该是所有符合要求中相差最小的一组m,n。

input
12
37 76 20 98 76 42 53 95 60 81 58 93

output

98 95 93
42 37 81
53 20 76
58 60 76

思路

一道稍微麻烦的模拟题。思路很容易想到,先找到符合要求的m,n,并对这组数从大到小排序,再模拟螺旋矩阵依次把数填进去。
找m,n。很容易知道,n必定小于等于N开方。从N的开方往下找,第一个能整除N的数即为n,m等于N/n。

调用sort对数列排序

螺旋矩阵从第一个开始往右,然后再往下,然后再往左,然后往上,往右…
很容易发现规律:
方向上:右到下 下到左 左到上 上到右
当碰到阻碍时会换方向(超出矩阵范围,碰到已经填充数的位置)

问题

模拟题一般想思路很简单,但细节很多。可能就一个条件错了最后的结果差了十万八千里。注意各种边界和坐标。

代码

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>

using namespace std;

int N, list[10007];

bool cmp(int a, int b){
	return a>b;
}

int factor(int N){		//返回n
	int n;
	n=sqrt(N);
	for(int i=n; i>=1; i--){
		if(N%i == 0){
			return i;
		}
	}
}

void matr(){
	int mat[107][107], vis[107][107], x=0, y=0, m, n;
	int direc[2]={0,1};
	memset(vis,0,sizeof(vis));
	n=factor(N);
	m=N/n;
	mat[0][0]=list[0];
	vis[0][0]=1;
	for(int i=1; i<N; i++){
		if(x+direc[1]<n&&x+direc[1]>=0&&y+direc[0]<m&&y+direc[0]>=0&&vis[y+direc[0]][x+direc[1]]==0){
			y+=direc[0];
			x+=direc[1];
			mat[y][x]=list[i];
			vis[y][x]=1;
//			printf("mat[%d][%d] = %d\n",y,x,mat[y][x]);
		}else{
			if(direc[0]==0){
				if(direc[1]==1){
					direc[0]=-1;
					direc[1]=0;
//					printf("right to down\n");
				}else{
					direc[0]=1;
					direc[1]=0;
//					printf("left to up\n");
				}
			}else if(direc[0]==-1){
				direc[0]=0;
				direc[1]=-1;
//				printf("down to left\n");
			}else if(direc[0]==1){
				direc[0]=0;
				direc[1]=1;
//				printf("up to right\n");
			}
			i-=1;
//			printf("i= %d\n",i);
		}
	}
	
	for(int i=0; i<m; i++){
		if(i!=0){
			printf("\n");
		}
		for(int j=0; j<n; j++){
			if(j!=0){
				printf(" ");
			}
			printf("%d",mat[i][j]);
		}
	}
}
int main()
{

//	int list[10007];
	scanf("%d",&N);
	for(int i=0; i<N; i++){
		scanf("%d",&list[i]);
	}
	sort(list, list+N,cmp);
//	for(int i=0;i<N;i++){
//		printf("%d ",list[i]);
//	}
//	printf("\n");
	matr();
	return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值