您的位置:首页 > 其它

【NOIP2014 普及组】螺旋矩阵

2017-08-18 01:37 218 查看

【NOIP2014 普及组】螺旋矩阵

一、题目

【NOIP2014 普及组】螺旋矩阵

时间限制: 1 Sec 内存限制: 128 MB

提交: 18 解决: 0

[提交][状态][讨论版]

题目描述

一个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。

二、分析及代码

【题解】

首先,本题有两种思路。

1.老老实实填数组。(此方法简单易懂,但当矩阵过大时,就会出现数组开不够大,或long long也不够的情况)

2. 用算法找规律,但规律不是一般的难找。我就简单说说我找到的规律。

1

2

3

4

12

13

14

5

11

16

15

6

10

9

8

7

1

2

4

3

首先对比两表,你就会发现下表就是上表中间四格每个减去12,正好就是外圈12个数中最大的;

而12就是外圈边长的4倍减4;

于是,就成了这样

1

2

3

4

12

1

2

5

11

3

4

6

10

9

8

7

红色是内圈,黑色是外圈

红色基数为12,黑色基数为0

同时,每一圈最上方的一行就是i+j-1的值。

最右方的一列就是i+j-1的值。

最下方的一行就是4n-i-j-1的值。

最左方的一列就是4n-i-j-1的值。

(一定要记得加上外圈基数哦!)

DP思路

状态:

用f
[i][j]表示n阶方块i,j位置的值。

对于外圈的:

i表示列,j表示行

if(i>=j)

f
[i][j]= i+j-1

if(i<j)

f
[i][j]= 4n-i-j-1

对于内圈:

f
[i][j]= f[n-2][i-1][j-1]+n*n-(n-2)*(n-2);

初始状态:

f[1][1][1]=1

f[2][1][1]=1

f[2][2][1]=2

f[2][2][2]=3

f[2][1][2]=4

外圈表示:

if(j==1||i==1||j==n||i==n)

内圈表示:

i>1&&i<n&&j>1&&j<n

代码

1 #include <iostream>
2 using namespace std;
3 int i=2,j=3,n=3;
4 void luo(int n1)
5 {
6     int a=0,k,l;
7     for (l=1;l<n1;l++)
8     {
9     a=a+n*4-l*8+4;
10     }
11     if (i>=j) printf ("%d",a+i+j-2*n1+1);
12         else printf ("%d",a+(n-2*n1+1)*4-i-j+n1+n1+1);
13 }
14 int main()
15 {
16     freopen("in2.txt","r",stdin);
17     int i1,j1;
18     scanf ("%d %d %d",&n,&j,&i);
19     //cout<<n<<j<<i;
20     i1=i;
21     j1=j;
22     if (i1>n/2) i1=n-i1+1;
23     if (j1>n/2) j1=n-j1+1;
24     if(i1>j1) luo(j1);
25         else luo(i1);
26 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: