题目链接:https://www.luogu.com.cn/problem/P2239
最暴力的解法就是从左上角开始遍历,一开始往右走,到头了右转往下走,到头了右转往左走,到头了右转往上走,……,一次循环。
此算法的时间复杂度为 (O(n^2) = O(9 imes 10^8)),在洛谷是可以过的。
但是我们其实可以把矩阵看成一个个圈,可以发现:最外面的圈一共有 (4 imes (n-1)) 个数字,第 (2) 外面的圈一共有 (4 imes (n-3)) 个数字,……,第 (i) 圈一共有 (4 imes (n-2 cdot i + 1)) 个数字……(如果 (n) 为奇数则最后那一圈就只有一个数字)。
而根据给我们的坐标 ((i,j)) 我们可以快速确定这个点在第 (k = min(min(i,n-i+1), min(j,n-j+1))) 圈,而第 (1) 圈到第 (k-1) 圈的数字总共有
[sum_{i=1}^{k-1} 4 imes (n - 2 cdot i + 1) = 4 cdot (n + 1 - k) cdot (k-1)
]
而第 (k) 圈的起始位置为 ((k,k)) ,我们从这里开始判断即可。
- 如果 (i = k),则 ((i,j)) 编号为 (4 cdot (n + 1 - k) cdot (k-1) + 1 + j - k);
- 否则,如果 (j = n+1-k),则 ((i,j)) 编号为 (4 cdot (n + 1 - k) cdot (k-1) + 1 + (n-2 cdot k+1) + i-k);
- 否则,如果 (i = n+1-k),则 ((i,j)) 编号为 (4 cdot (n + 1 - k) cdot (k-1) + 1 + 2 cdot (n-2 cdot k+1) + (n+1-k)-j);
- 否则,如果 (j = k),则 ((i,j)) 编号为 (4 cdot (n + 1 - k) cdot (k-1) + 1 + 3 cdot (n-2 cdot k+1) + (n+1-k) - i)。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
int n, i, j, k, ans;
int main() {
cin >> n >> i >> j;
k = min( min(i, n+1-i), min(j, n+1-j) );
ans = 4 * (n+1-k) * (k-1) + 1;
if (i == k) ans += j-k;
else if (j == n+1-k) ans += (n-2*k+1) + i-k;
else if (i == n+1-k) ans += 2*(n-2*k+1) + (n+1-k)-j;
else ans += 3*(n-2*k+1) + (n+1-k)-i;
cout << ans << endl;
return 0;
}