• 上次写的记录 未AC错误代码,仅错误思路记录

    又把这题写了一次,因为有了之前的思路,所以直接按照思路来拆解。

    在下标的推断中还是耗了不少时间,像下面这个图一样,要把每层循环的上下左右边界分别拆开,然后分别列出不同边界第一层和第二层下标的表达式,而且还要考虑,变量 m n 之间与实际下标 -1 的关系。

    1050 螺旋矩阵 (25 point(s)) (含部分测试数据)_打印图案

    推导的时候还是有点小问题,变量太多思路有点混乱。可能一次性考虑的关系还是太多了,应该先考虑不带下标和变量转换,或者先把 m n 转换成真正的下标的边界,总之先用一个统一的规则将循环运动模拟出来,再考虑转换问题。

  • 下面是测试时用到一些测试数据,发现了一些边界问题。比如只有一个元素的情况(第一组数据)。或者是上边界输出完,但是下边界判断可以循环,导致原位置的数据被覆盖的问题(第二第三组数据)。

    不过这两个其实都可以归结一个问题,就是判断元素是否输出完,所以在下 左边界的循环处都有一个 v != N 的判断。

    1
    1
    
    16
    37 76 20 98 76 42 53 95 60 81 58 93 30 18 15 11
    
    18
    37 76 20 98 76 42 53 95 60 81 58 93 30 18 15 11 13 17
    
#include <bits/stdc++.h>
using namespace std;

int main() {
	int N;
	cin >> N;
	vector<int> V(N);
	
	for(int i = 0; i < N; i++)
		cin >> V[i];
	sort(begin(V), end(V), greater<int>());
	
	// 算出m n
	int n = sqrt(N);
	int m = N / n;
	while(m * n != N){
		n--;
		m = N / n;
	}
	// 获取循环次数
	int v = 0, step = (n + 1) / 2, ans[m][n] = {0};
	for(int s = 0; s < step; s++){
		for(int up = s; up <= n - 1 - s; up++)
			ans[s][up] = V[v++];
		
		for(int right = 1 + s; right <= m - 2 - s; right++)
			ans[right][n-1-s] = V[v++];
			
		for(int down = n - 1 - s; down >= s && v != N; down--)
			ans[m-1-s][down] = V[v++];
			
		for(int left = m - 2 - s; left >= 1 + s && v != N; left--)
			ans[left][s] = V[v++];
	} 
	
	for(int i = 0; i < m; i++){
		for(int j = 0; j < n; j++)
			cout << (j ? " " : "") << ans[i][j];
		cout << endl;
	}
}