【NOIP2014 普及组】螺旋矩阵

【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[n][i][j]表示n阶方块i,j位置的值。

对于外圈的:

i表示列,j表示行

if(i>=j)

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

if(i<j)

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

对于内圈:

f[n][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 }

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值