一、题目
一个 nn 行 nn 列的螺旋矩阵可由如下方法生成:
从矩阵的左上角(第 11 行第 11
列)出发,初始时向右移动;如果前方是未曾经过的格子,则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。根据经过顺序,在格子中依次填入
11, 22 , 33, … , nn ,便构成了一个螺旋矩阵。下图是一个 n = 4 时的螺旋矩阵。
输入格式:
输入共一行,包含三个整数 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
二、思路
当n=4时,螺旋矩阵如下:
当n=5时,螺旋矩阵如下:
1、暴力解法
我们先找到螺旋的四个角的坐标:
(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循环来完成对矩阵的值的输入.
易错提示:
但是由于使用到了数组,所以在实际输出的时候,我们需要将坐标–;才能达到正确输出的目的。
2、进阶递归
掌握了基础解法以后,继续观察矩阵,我们还能发现以下规律:
以n = 4时为例
我们可以发现,里层实际上也是一个螺旋矩阵,只不过是初始值变成了12,而阶数(n)减少了2,所以我们可以每次只表示一圈,然后进行递归,同样可以表示出螺旋矩阵。
对于阶数(n)的奇偶,结束的标准也不同,所以我们需要进行分类讨论:
①奇数的结束是矩阵的中心(n * n);
②偶数的结束是最里层的矩阵(n = 2,只是初始值改变了)
经过上一次坐标出错后,我们索性直接从1开始遍历(这样坐标就不用–了)。
三、代码
1、暴力解法
#include<stdio.h>
int main()
{
int n,i,j;
scanf("%d %d %d",&n,&i,&j);