【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 }