描述
一个 n 行 n 列的螺旋矩阵可由如下方法生成:
从矩阵的左上角(第 1 行第 1 列)出发,初始时向右移动;如果前方是未曾经过的格子, 则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。根据经过顺序,在格子中 依次填入 1, 2, 3, ... , n2,便构成了一个螺旋矩阵。
下图是一个 n = 4 时的螺旋矩阵。
11211102131693141584567
现给出矩阵大小 n 以及 i 和 j,请你求出该矩阵中第 i 行第 j 列的数是多少。
格式
输入格式
输入共一行,包含三个整数 n,i,j,每两个整数之间用一个空格隔开,分别表示矩阵大小、待求的数所在的行号和列号。
输出格式
输出共一行,包含一个整数,表示相应矩阵中第 i 行第 j 列的数。
样例1
样例输入1[复制]
4 2 3
样例输出1[复制]
14限制
对于 50%的数据,1 ≤ n ≤ 100; 对于 100%的数据,1 ≤ n ≤ 30,000,1 ≤ i ≤ n,1 ≤ j ≤ n。
解析:将整个矩阵看成 “回” 形状的分层结构,然后进行去层处理,使得要求得(i,j)处于最外层,然后再分情况讨论。来源
NOIP2014 普及组
1.等差数列求和。
最外面的一层共有数: 4*n-4
第二层共有数: 4*n-4 -8
.. ....
假设(i,j)外共有 x 层,则外层所有的数为:ans=4*n*x-4*x*x。
![]()
接下来就是分情况讨论当(i,j)处于矩阵最外层时,位于(i,j)的数是多少。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int main() //模拟类题目
{
int n,i,j,k,x,ans;
cin>>n>>i>>j;
x=min(i-1,n-i);//以下三行是寻找距离边界最小的距离,也就是找外边的层数x
x=min(x,j-1); //也就是找i-1,n-i,j-1,n-j中最小的那个数
x=min(x,n-j);
ans=4*n*x-4*x*x;
if(i-x==1)ans+=j-x; //x=i-1的时候,也就是在该层最上边一行,所以需要加的数就是j-x;
else
if(i+x==n)ans+=3*n-5*x-1-j;//x=n-i的时候,也就是在该层最下边一行,需要加的数是2*(n-2x-1)+(n-x)-j+1
else
if(j-x==1)ans+=4*n-7*x-2-i;//x=j-1的时候,也就是在该层最左侧,但不在上下两行,需加的数是3*(n-2x-1)+(n-x)-i+1;
else ans+=n-3*x+i-1; //x=n-j的时候,也就是在该层的最右边,但不在上下两行,需加的数是(n-2x-1)+(i-x)
cout<<ans;
return 0;
}
【递归解法】
#include<iostream>
using namespace std;
int n,x,y;
int jz(int n,int i,int j)
{
if(i==1)
return j;//如果所求坐标在第一行,那么这个坐标上的数就是纵坐标
if(i==n)
return 3*n-1-j;//如果所求坐标在最后一行
if(j==1)
return 4*n-2-i;//如果所求坐标在第一列
if(j==n)
return n+i-1;//如果所求坐标在最后一列
return jz(n-2,i-1,j-1)+(n-1)*4;//如果都没有,说明 所求坐标在中间,递归下一层;
}
int main()
{
cin>>n>>x>>y;
cout<<jz(n,x,y)<<endl;
return 0;
}