题目描述
一个n行n列的螺旋矩阵可由如下方法生成:
从矩阵的左上角(第1行第1列)出发,初始时向右移动;如果前方是未曾经过的格子,则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。根据经过顺序,在格子中依次填入1, 2, 3, ... , n,便构成了一个螺旋矩阵。2
下图是一个n = 4 时的螺旋矩阵。
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
现给出矩阵大小n以及i和j,请你求出该矩阵中第i行第j列的数是多少。
输入描述
输入共一行,包含三个整数 n,i,j,每两个整数之间用一个空格隔开,分别表示矩阵大小、待求的数所在的行号和列号。
输出描述
输出共一行,包含一个整数,表示相应矩阵中第i行第j列的数。
样例输入
4 2 3
样例输出
14
数据范围及提示
对于50%的数据,1 ≤ n ≤ 100;
对于100%的数据,1 ≤ n ≤ 30,000,1 ≤ i ≤ n,1 ≤ j ≤ n。
【RE解法】模拟矩阵,能拿50分,不多说
#include <iostream>
using namespace std;
int a[5000][5000];
bool flag = false;
int n, m, i, j, c, nowx, nowy;
int u=-1, d, l=-1, r;
int main() {
cin >> n >> i >> j;
i --;
j --;
d=n;
r=n;
while(true) {
while(true) {
c ++;
a[nowy][nowx] = c;
if(nowx == j && nowy == i) {
cout << c << endl;
return 0;
}
if(nowx+1 >= r) break;
if(a[nowy][nowx+1] != 0) break;
nowx ++;
}
c --;
while(true) {
c ++;
a[nowy][nowx] = c;
if(nowx == j && nowy == i) {
cout << c << endl;
return 0;
}
if(nowy+1 >= d) break;
if(a[nowy+1][nowx] != 0) break;
nowy ++;
}
c --;
while(true) {
c ++;
a[nowy][nowx] = c;
if(nowx == j && nowy == i) {
cout << c << endl;
return 0;
}
if(nowx-1 <= l) break;
if(a[nowy][nowx-1] != 0) break;
nowx --;
}
c --;
while(true) {
c ++;
a[nowy][nowx] = c;
if(nowx == j && nowy == i) {
cout << c << endl;
return 0;
}
if(nowy-1 <= u) break;
if(a[nowy-1][nowx] != 0) break;
nowy --;
}
c --;
}
return 0;
}
【AC解法】分类讨论 总结通项公式
layer:由外到内是第几层
情况1:在第i行就是在第i层
例如在第1行,就是第1层
情况2:在第i行,实际是倒数第n-i+1行 在第(n-i+1)层
例如在第n行,实际在第1层(n-n+1)
情况3:在第j列就是在第j层
例如在第1列就是第1层
情况4:在第j列是从右往左数第n-j+1列 在第(n-j+1)层
例如在第n列是第1层
取min就是从上下左右四个方向数层数,哪一种最小就是第几层
先根据面积计算左上角的数字;
根据题目要求的点的位置分四种情况:
如果在上边上,直接往右数
如果在右边上,先往右数,再往下数
如果在下边上,先往右,再往下,再往左
如果在左边上,先往右,再往下,再往左,最后往上
【AC_Code】
#include <iostream>
using namespace std;
inline int Min4(const int a, const int b, const int c, const int d) {
return min(a, min(b, min(c, d))); //求四个数的最小值
}
int Get(int n, int i, int j) {
int ans;
int layer = Min4(i, j, n-i+1, n-j+1); //层
int corner = n * n - (n-2*layer+2)*(n-2*layer+2) + 1; //corner:这一层第一个数(左上角),根据面积求
if(layer == i) //如果在上边上,直接往右数
ans = corner + (j-layer);
else if(layer == n-j+1) //如果在右边上,先往右数,再往下数
ans = corner + (j-layer) + (i-layer);
else if(layer == n-i+1) //如果在下边上,先往右,再往下, 再往左
ans = corner + (n-2*layer+1) + (n-2*layer+1) + ((n-layer+1)-j);
else if(layer == j) //如果在左边上,先往右,再往下, 再往左,最后往上
ans = corner + (n-2*layer+1) + (n-2*layer+1) + (n-2*layer+1) + ((n-layer+1)-i);
/*以上可以合并简化方便计算,为了理解方便就不合并了*/
return ans;
}
int main() {
int n, i, j;
//cin >> n;
cin >> n >> i >> j;
//for(int i=1; i<=n; i++, cout << endl)
// for(int j=1; j<=n; j++) cout << Get(n, i, j) << ' ';
cout << Get(n, i, j) << endl;
return 0;
}
Thanks#end