欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【PAT】1105 Spiral Matrix(柳婼的思想详细解读)

程序员文章站 2024-03-14 22:00:05
...

【PAT】1105 Spiral Matrix

用的就是是柳大姐的思想:柳姐传送门
先计算行数m和列数n的值,n从根号N的整数部分开始,往前推一直到1,找到第一个满足N % n== 0的,m的值等于N/n~将N个给定的值输入数组a,并将a数组中的值按非递增排序,接着建立m行n列的数组b,填充时按层数填充,一个包裹矩阵的口字型为一层,计算螺旋矩阵的层数level,如果m的值为偶数,层数为m/2,如果m为奇数,层数为m/2+1,所以level = m / 2 + m % 2;因为是从左上角第1个格子开始,按顺时针螺旋方向填充,所以外层for循环控制层数i从0到level,内层for循环按左上到右上、右上到右下、右下到左下、左下到左上的顺序一层层填充,注意内层for循环中还要控制t <= N – 1,因为如果螺旋矩阵中所有的元素已经都填充完毕,就不能再重复填充~填充完毕后,输出整个矩阵~
【PAT】1105 Spiral Matrix(柳婼的思想详细解读)
下面以一个5*4的矩阵为例:(m=5,n=4)
【PAT】1105 Spiral Matrix(柳婼的思想详细解读)
可以看到每一层都需要分为四个步骤进行填充数字。若将元素的下标看成是一个x,y的坐标,我们很容易就可以总结出①②③④遍历过程中x,y的取值范围。其中i表示正在填充第i层,从0开始。

① x:i              y:i ~ n-i-1
② x:i+1 ~ m-i-2    y:n-i-1
③ x:m-1-i          y:n-i-1 ~ i
④ x:m-i-2 ~ i+1    y: i

在每一轮循环遍历的过程中,我们还需要进行 cnt <= N - 1 的判断(否则会有测试点通不过,例如:只有19个元素,13个元素的时候,大家可以试一试)。其中cnt表示已经填充元素的个数,而N表示元素总个数。

AC代码:

#include<bits/stdc++.h>
using namespace std;
vector<int> v;
int cmp(int a, int b) {
	return a > b;
}
int main() {
	int N,m,n; scanf("%d", &N);
	for (int i = 0; i < N; i++) {
		int temp; scanf("%d", &temp);
		v.push_back(temp);
	}
	sort(v.begin(), v.end(), cmp);
	n = (int)sqrt(N);
	while (N%n) n++;//N%n==0时退出循环
	m = N / n;
	if (m < n) swap(n, m);//保持m>=n;
	vector<vector<int> > ans(m, vector<int>(n));
	int level = n / 2 + n % 2;//计算一共有几层。
	int cnt = 0;//记录当前数组的下标
	for (int i = 0; i < level; i++) {//此时开始遍历每一层
		for (int j = i; j < n - i && cnt <= N - 1; j++)//①
			ans[i][j] = v[cnt++];
		for (int j = i + 1; j < m - i - 1 && cnt <= N - 1; j++) //②
			ans[j][n - 1 - i] = v[cnt++];
		for (int j = n - i - 1; j >= i && cnt <= N - 1; j--)//③
			ans[m - i - 1][j] = v[cnt++];
		for (int j = m - i - 2; j >= i + 1 && cnt <= N - 1; j--)//④
			ans[j][i] = v[cnt++];
	}
	for (int i = 0; i < m; i++) {
		cout << ans[i][0];
		for (int j = 1; j < n; j++) {
			cout<<" "<< ans[i][j];
		}
		cout << endl;
	}
}