-
上次写的记录 未AC错误代码,仅错误思路记录 。
又把这题写了一次,因为有了之前的思路,所以直接按照思路来拆解。
在下标的推断中还是耗了不少时间,像下面这个图一样,要把每层循环的上下左右边界分别拆开,然后分别列出不同边界第一层和第二层下标的表达式,而且还要考虑,变量 m n 之间与实际下标 -1 的关系。
推导的时候还是有点小问题,变量太多思路有点混乱。可能一次性考虑的关系还是太多了,应该先考虑不带下标和变量转换,或者先把 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;
}
}