|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 陈尚涵 于 2024-2-3 10:20 编辑
前言:
事情是酱的 2024/1/24,我看到了@zhangjinxuan 发的这么一则帖子:https://fishc.com.cn/thread-239305-1-1.html
在之前,我是做过螺旋矩阵的题的,当时呢第一时间想到用数学,但是想了想似乎不是很简单就直接用暴力了
现在看到 zhangjinxuan 的帖子,我又开始思考这个问题,但是我太弱了,当时想了0.5h才想出来
btw,这个主题我托更了亿点点,各位见谅
问题:
虽然 zhangjinxuan 已经发了问题,但是我再重申一遍
对于N*N的矩阵,令原点为左上角为(1,1),并使x从左向右增大,y从上向下增大
接着从原点开始,逆时针(注意这里是逆时针,有的螺旋矩阵是顺时针)绕着矩阵每次增大1(到角落拐弯)
比如,N=5的:
- 1 16 15 14 13
- 2 17 24 23 12
- 3 18 25 22 11
- 4 19 20 21 10
- 5 6 7 8 9
复制代码
求通项公式(即数学算法)并达到O(1)
解法:
解法说难不难,说简单不简单,对萌新来说不太好推,大犇又不屑于推
首先就是检查(x,y)地方所处的层数(转一圈为1层,初始第一层),每一层都有四个部分
但是都有一个共同点,那就是距离边缘的距离+1=层数,稍加思考就可以写出,层数(设为d)=$min(x,y,n-x+1,n-y+1)$,所以就可以写出代码了
- int d = fourmin(x, y, n-x+1, n-y+1);
复制代码
此外,由于min不支持4个,所以要自定义一下fourmin
- int fourmin(int a, int b, int c, int d){
- int abmin = min(a,b);
- int cdmin = min(c,d);
- return min(abmin,cdmin);
- }
复制代码
接下来有了层数之后,我们就要统计这层以前所有层数的数量,并设置为初始值
那么一层一层来,我们知道一层的数量=4(边长-1)
又边长=$n-2(d-1)$
所以说一层的数量应该是$4(n-2(d-1)-1)$
但是咱们要求的所有层的,所以说设求前m层,数量为$\sum\limits_{c=1}^{m}4(n-2(c-1)-1)$
简单因式分解一下就是$4(nm-m-m(m-1))$
这里我们应该求前(d-1)层,所以说就可以设初始值了,写出代码(为了方便,直接--)
- d--;
- int a = 4*(n*d-d-d*(d-1))+1;
- d++;
复制代码
这里我+1是个伏笔,为了后面的程序
这样的话,咱们就要分四种情况了,一层分上下左右,这个怎么判定?想想开头,只需要用层数判定就可以了
- if (d == x){
- } else if (d == n-y+1){
- } else if (d == n-x+1){
- } else if (d == y){
- }
复制代码
接着就要考虑每种情况怎么去计算,由于咱们提前+1,所以咱们每个边长只需要加边长-1就可以了,也就是$n-2(d-1)-1$
左就是0个边长,下就是1个边长,右就是2个边长,上就是3个边长
但是除了边长还需要判定剩余的一个缺失的边长,怎么判定?还是用层数!这个层数还是非常有用的,因为这里层数可以帮我们快速定位这一行的第一个
综上,写出
- if (d == x){
- a += y-d;
- } else if (d == n-y+1){
- a += (n-2*(d-1)-1)+(x-d);
- } else if (d == n-x+1){
- a += 2*(n-2*(d-1)-1)+(n-d+1-y);
- } else if (d == y){
- a += 3*(n-2*(d-1)-1)+(n-d+1-x);
- }
复制代码
好的,这样就完结了,来看下整个程序
- #include <iostream>
- using namespace std;
- int fourmin(int a, int b, int c, int d){
- int abmin = min(a,b);
- int cdmin = min(c,d);
- return min(abmin,cdmin);
- }
- int main(){
- int x, y, n;
- cin >> x >> y >> n;
- int d = fourmin(x, y, n-x+1, n-y+1);
- d--;
- int a = 4*(n*d-d-d*(d-1))+1;
- d++;
- if (d == x){
- a += y-d;
- } else if (d == n-y+1){
- a += (n-2*(d-1)-1)+(x-d);
- } else if (d == n-x+1){
- a += 2*(n-2*(d-1)-1)+(n-d+1-y);
- } else if (d == y){
- a += 3*(n-2*(d-1)-1)+(n-d+1-x);
- }
- cout << a;
- return 0;
- }
复制代码
结尾
求各位大犇赐教@zhangjinxuan @liuhongrun2022 @歌者文明清理员 @一点沙 @tommyyu
(没有 人造人 好友 )
对托更非常抱歉,所以撒个币吧
|
评分
-
查看全部评分
|