一个 nn 行 nn 列的螺旋矩阵可由如下方法生成:
从矩阵的左上角(第 11 行第 11
列)出发,初始时向右移动;如果前方是未曾经过的格子,则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。根据经过顺序,在格子中依次填入
11, 22 , 33, … , nn ,便构成了一个螺旋矩阵。
输入格式:
输入共一行,包含三个整数 n,i,jn,i,j ,每两个整数之间用一个空格隔开,分别表示矩阵大小、待求的数所在的行号和列号。
输出格式:
输出一个整数,表示相应矩阵中第 ii 行第 jj 列的数。
数据范围 对于 50%50% 的数据, 1 \le n \le 1001≤n≤100 ;
对于 100%100% 的数据, 1 \le n \le 30,0001≤n≤30,000 , 1 \le i \le n,1 \le j
\le n1≤i≤n,1≤j≤n
Sample Input:
4 2 3
Sample Output:
14
我们先找到螺旋的四个角的坐标:
(0,0)->(0,n - 1)->(n - 1,n - 1)->(n - 1,0)
这样一次是一个循环。
然后我们可以确定循环的次数,不超过 n / 2 次(n为偶数的情况),但是当 n 为奇数的时候,矩阵的中心的值为 n * n,我们可以单独讨论。
通过观察螺旋矩阵,我们通过其原理可以发现,其坐标有如下规律:
当矩阵的方向为:“向右” ,此时坐标的纵坐标不变,横坐标++;
改变范围:0 ~ n - 1
当矩阵的方向为:“向下” ,此时坐标的纵坐标++,横坐标不变;
改变范围:0 ~ n - 1
当矩阵的方向为:“向左” ,此时坐标的纵坐标不变,横坐标–;
改变范围:n - 1 ~
当矩阵的方向为:“向上” ,此时坐标的纵坐标–,横坐标不变;
改变范围:
通过以上坐标的基础规律,我们就可以用四个for循环来完成对矩阵的值的输入.
易错提示:
但是由于使用到了数组,所以在实际输出的时候,我们需要将坐标–;才能达到正确输出的目的。
掌握了基础解法以后,继续观察矩阵,我们还能发现以下规律:
以n = 4时为例
我们可以发现,里层实际上也是一个螺旋矩阵,只不过是初始值变成了12,而阶数(n)减少了2,所以我们可以每次只表示一圈,然后进行递归,同样可以表示出螺旋矩阵。
对于阶数(n)的奇偶,结束的标准也不同,所以我们需要进行分类讨论:
①奇数的结束是矩阵的中心(n * n);
②偶数的结束是最里层的矩阵(n = 2,只是初始值改变了)
经过上一次坐标出错后,我们索性直接从1开始遍历(这样坐标就不用–了)。
#include
int main()
{
int n,i,j;
scanf("%d %d %d",&n,&i,&j);
int x[300][300] = {1};// 将数组初始化为1,考虑了n = 1时的情况
int a,b;
int num = 1;
for(a = 0;a <= n/2;a++)
{
// 上边框
for(b = a;b <= n - a -1;b++)
x[a][b] = num++;
// 右边框
for(b = a + 1;b <= n - a - 1;b++)
x[b][n - a - 1] = num++;
// 下边框
for(b = n - a - 2;b >= a;b--)
x[n - a - 1][b] = num++;
// 左边框
for(b = n - a - 2;b > a;b--)
x[b][a] = num++;
// n为奇数的情况
if(n % 2 == 1)
x[n/2][n/2] = n * n;
}
printf("%d",x[i - 1][j - 1]);
return 0;
}
#include
int a[300][300] = {0};
void func(int num,int max,int len,int t,int n)
{
if(len == 1)// n为奇数时,结束的标志
{
a[t][t] = num;
}
else if(len == 2)// n为偶数时,结束的标志
{
a[t][t] = num++;
a[t][t+1] = num++;
a[t + 1][t + 1] = num;
a[t + 1][t] = max;
return;
}
int flag = n + 1 - t;
int Num = num;
int i,j = 0;
// 上边框
for(j = t;j <= flag;j++)
a[t][j] = Num++;
// 右边框
for(i = t + 1;i <= flag;i++)
a[i][flag] = Num++;
// 下边框
for(j = flag - 1;j >= t;j--)
a[flag][j] = Num++;
// 左边框
for(i = flag - 1;i >= t + 1;i--)
a[i][t] = Num++;
func(Num,n * n,len - 2,t + 1,n);
}
int main()
{
int n,i,j;
scanf("%d %d %d",&n,&i,&j);
func(1,n * n,n,1,n);
printf("%d",a[i][j]);
return 0;
}