1. 程式人生 > >#138-(EZOI模擬賽)【數學技巧】旋轉矩陣

#138-(EZOI模擬賽)【數學技巧】旋轉矩陣

Description

一個n行n列的螺旋矩陣可由如下方法生成:

從矩陣的左上角(第1行第1列)出發,初始時向右移動;如果前方是未曾經過的格子,則繼續前進,否則右轉;重複上述操作直至經過矩陣中所有格子。根據經過順序,在格子中依次填入1, 2, 3, ... , n,便構成了一個螺旋矩陣。

下圖是一個n = 4 時的螺旋矩陣。

1 2 3 4

12 13 14 5

11 16 15 6

10 9 8 7

現給出矩陣大小n以及i和j,請你求出該矩陣中第i行第j列的數是多少。

Input

共一行,包含三個整數 n,i,j,每兩個整數之間用一個空格隔開,分別表示矩陣大小、待求的數所在的行號和列號。

Output

一個整數,表示相應矩陣中第i行第j列的數。

Sample Input

4 2 3

Sample Output

14

HINT

【資料說明】

對於50%的資料,1≤n≤100;

對於100%的資料,1 ≤ n ≤ 30,000,    1 ≤ i ≤ n,   1 ≤ j ≤ n。

先得到該數在第幾圈,然後在這一圈暴力找。

#include <iostream>
#include <cmath>

#define SIZE 30010

using namespace std;

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};

int main(void)
{
	int n, ex, ey, x = 1, y = 1, r, c, dis = 1, d = 0, uplimit, downlimit, k, temp = 1;
	
	scanf("%d%d%d", &n, &ex, &ey);
	
	k = min(min(ex, ey), min(n - ex, n - ey) + 1); // 在第幾圈
	uplimit = k; // 上限
	downlimit = n - k + 1; // 下線
	while (--k)
	{
		temp -= 2;
		dis += (n + temp) << 2;
	}
	if ((ex == uplimit) && (ey == uplimit))
	{
		printf("%d", dis);
		return 0;
	}
	x = y = uplimit;
	for ( ; ; ) // 暴力找
	{
		++dis;
		r = x + dx[d];
		c = y + dy[d];
		if (((r < uplimit) || (r > downlimit)) || ((c < uplimit) || (c > downlimit))) // 需要換方向
		{
			++d;
			d %= 4;
			r = x + dx[d];
			c = y + dy[d];
		}
		if ((r == ex) && (c == ey)) // 找到結果
		{
			printf("%d", dis);
			return 0;
		}
		x = r;
		y = c;
	}
	
	return 0;
}