求螺旋矩阵任意位置元素 洛谷P2239 您所在的位置:网站首页 蛇形矩阵找数的位置 求螺旋矩阵任意位置元素 洛谷P2239

求螺旋矩阵任意位置元素 洛谷P2239

2023-08-07 09:29| 来源: 网络整理| 查看: 265

 

之前在矩阵的模拟中,发过几篇输出螺旋矩阵的题目:输出螺旋矩阵,这几天又遇到了螺旋矩阵的新题目,不让你输出螺旋矩阵,而是给你一个下标(x,y),输出当前 矩阵元素 的值。

题目描述

一个n行n列的螺旋矩阵可由如下方法生成: 从矩阵的左上角(第1行第1列)出发,初始时向右移动;如果前方是未曾经过的格子,则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。根据经过顺序,在格子中依次填入1,2,3,...,n2,便构成了一个螺旋矩阵。 下图是一个n=4时的螺旋矩阵。

现给出矩阵大小n以及i和j,请你求出该矩阵中第i行第j列的数是多少。

输入

输入共一行,包含三个整数 n,i,j,每两个整数之间用一个空格隔开,分别表示矩阵大小、待求的数所在的行号和列号。1≤n≤30000,1≤i≤n,1≤j≤n

 

输出

输出共一行,包含一个整数,表示相应矩阵中第i行第j列的数。

这题看到之后最朴素的思路就是,将螺旋矩阵打印,然后直接用O(1)的复杂度求出 (x,y)的值。结果TLE,因为我们看到n的范围30000,输出一个螺旋矩阵,需要内存n^2,时间n^2,所以无论从内存上还是时间上,这都不是一个好的办法,所以我们需要换一种思路。

所有人都会的思路,找规律-----我们根据题目可以知道这个元素的值百分百与x,y有关,不然他不可能给你(根据做题经验)。

那么,真的有规律吗?我们以一个矩阵来看,一般来说这种题奇数难判断,因为奇数多出一个数,所以我们以奇数为例。

(也许题目给你这个4*4就是为了让你找错规律,可恶的出题人)

下面附一个5*5的矩阵:

不同层颜色进行了区分,现在我们找一下规律:

x为所求元素,(i ,  j)  分别为x,y坐标:

1.第一行 : 我们发现纵坐标就是所求元素的值,即【if(i==1)  x=j;】

2.第二行 :我们发现找不到与横纵坐标有关的通式,并且在第n行之前x,y坐标没有一个通式表示,因为前面17 18 19 6没有通式。

3.第n行:他是一个递减的通式。我们把他与列连起来,就是3*n-1-j。

4.同样的,第一列通式:4*n-2-i,第n列通式:n+i-1。

5.这个时候注意,假设我们要求的这个元素是(1,5),那么它既满足i==1,又满足j==n,这两个用哪个通式都可以求解,并且结果都是一样的,但是!细心一点会发现 如果输入(1,1),既满足i==1,j==1。但他却不满足j==1时的通式。所以我们将j==1放到最后一个判断,如下图所示代码:

if(i==1) x=j; else if(j==n) x=n-1+i; else if(i==n) x=n*3-j-1; else if(j==1) x=4*n-i-2;

这样就能避免错误,为什么呢?经过上面三个判断,如果拿上图来说就只有元素 14 15 16没有被判断,而这三个绝对都符合j==1的通式。

6.好了规律也找到了,但是现在我们只能确定满足四种坐标的值,如果(2,3)怎么办:

继续看这个图,我们发现第二层(黄色),其实就是由16推出来的,并且第二层所有的数,满足另一个螺旋矩阵,比如17=16+1,18=16+2。

其实就是这么一个图(为了方便我手写)

1    2   3     4     5

16  1   2     3    6

15  8   1    4    7

14  7    6    5   8

13 12  11  10  9

我们发现,如果要求第二层的某个数,只需要将他的上一层(第一层)的(2,1)位置的这个数加上。因为我们只知道最外层的规律,就需要将第二层成为最外层然后就可以直接算出某一个的值,然后加上上一层(2,1)这个位置的数,如果要把第二层当做最外层只需要n-2,可以举例试试。实在不懂看一下我手写的这个表,第二层成了一个从1开始的n=3的螺旋矩阵外层。

所以我们就可以根据这个思想,进行递归了。

第一步:首先判断这是不是最外层的点。

第二步:如果不是现在最外层的点,让他成为最外层(N-2,i-1,j-1)坐标要对应减一,因为上面一行没了,左边一行也没了。

第三步:如果是最外层的点,我们就retun对于这一层是最外层的值。然后在一次次由外往里面刨的过程中,每一个过程都保留(2,1)位置的值加上,这个地方如果递归不太懂,可能有点难理解。

PS:还有(2,1)这个位置的值是什么呢?就是4*(n-1),假设最外层每条边都有n-1个值。

具体看代码叭:

#include #include #include #include #include #include #include #include #define MIN(x,y) ((x)(y)?(x) : (y)) using namespace std; typedef long long ll; const int maxn=1e6+5; const ll INF=1e9; /*坚持不懈,无懈可击*/ /*中国有句古话,叫做置之死地而后生!*/ int bg(int n, int i, int j) { if(i==1) return j; if(j==n) return n-1+i; if(i==n) return n*3-j-1; if(j==1) return 4*n-i-2;//以上就是如果当前的点就是最外层,直接返回 return 4*n-4+bg(n-2,i-1,j-1);//如果不是最外层,就让下一层的成为最外层,并且要加上【这一层】!!!!(2,1)位置上的值。 } int main() { int n,x,y; scanf("%d",&n); scanf("%d%d",&x,&y); printf("%d\n",bg(n,x,y)); return 0; }

 这样基本这道题就完成了,祝大家一次AC。

在仔细想想,其实做这种题,心里清楚如果暴力绝对会超时,而且内存会炸,那么我们只能找规律,根据题目的x,y找规律。好叭,其实身边朋友很多做出来没有用递归。那也怪我思维太弱了。就这样叭,继续加油!

update 2019.9.3更新高效算法:

#include using namespace std; typedef long long ll; ll n; ll work(ll n,ll a,ll b) { ll q=min(min(a,b),min(n-a+1,n-b+1)); ll ans; if(a


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有