• 蛇形数组和直接计算编号


    先看两个示例:

    这两个数组一个宽度是5,一个宽度是4。以左图为例如果要在数组里面蛇形输出,从1开始x递增,到达5时改为y递增,到达9时x递减,13时y递减(注意此时的miny)完成一圈进入内圈。这样就可以在数组里面输出这些数字。在NOI上做了一个小兔子捡金币的问题,如果在M*M的矩阵内,每个点有一个金币,小兔子按以下规则从左上角开始捡金币:前方没有金币时右转,前方有金币时继续向前,问小兔子达到(X,Y)时有多少个金币。这就是一个典型的蛇形访问数组的问题,只不过这个问题不一定要逐个访问,可以根据X,Y计算出来。

      观察左右两图,每一圈被划分为4个段:红色字体-蓝色字体-绿色字体-黑色字体。左图和右图有一点不同:在圈缩小过程中,内圈比外圈宽度少2,左图初始宽度为奇数,退化的最终结果是一个点。所以,我们可以知道,每一圈的元素数为:4*(len-1)。可以使用从外向内遍历的方式判断(X,Y)是否在一圈上,也可以直接根据(X,Y)判断在哪一圈。后者实现时需要先计算一个数组:记录经过N个外圈时编号行进了多少;前者边计算边记录这个编号偏移量,而且编码比较简单。所以,采用逐圈判定的方法即可:

    #include<iostream>
    #include<cstring>
    using namespace std;
    struct point{
        int x;
        int y;
        point(){
            this->x=0;
            this->y=0;
        }
        point(int x,int y){
            this->x=x;
            this->y=y;
        }
    };
    int idxinrect(point lt,point rd,point p,int curlen){
        if(p.y==lt.y && p.x<rd.x){                //上边
            return p.x-lt.x+1;
        }else if(p.x==rd.x && p.y<rd.y){        //右边
            return curlen+p.y-lt.y+1;
        }else if(p.y==rd.y && p.x>lt.x){        //下边
            return curlen*2+rd.x-p.x+1;
        }else if(p.x==lt.x && p.y>lt.y){        //左边
            return curlen*3+rd.y-p.y+1;
        }
        return -1;
    }
    int search(point p,int size){
        int lastid,curlen,id;
        point lt=point(1,1),rd=point(size,size);
        lastid=0;
        curlen=size-1;
        while(curlen>0){                    
            id=idxinrect(lt,rd,p,curlen);    //在这一圈上的时候返回在这一圈内的偏移,否则返回-1。
            if(id!=-1){
                return lastid+id;
            }
            lastid+=curlen*4;                //记录这一圈的长度
            lt.x++;lt.y++;                    //缩小到下一圈
            rd.x--;rd.y--;
            curlen-=2;
        }
        if(curlen==0){                        //0时退化为一个点。就是中间一点,其编号为size*size。
            return ++lastid;
        }
        return -1;
    }
    int main()
    {
        int i,k,n;
        point p;
        cin>>k>>n;
        for(i=0;i<k;i++){
            cin>>p.x>>p.y;   //若用于解题,互换此处的.x.y
            cout<<search(p,n)<<endl;
        }
    }

    代码中单独处理了初始外圈长度为奇数(最内圈为1个点)的情况。正如后添加注释中的内容,横纵坐标傻傻搞不清……

  • 相关阅读:
    JS函数的定义与调用方法
    一次完整的浏览器请求流程
    【前端安全】JavaScript防http劫持与XSS
    深入理解display属性
    前端开发人员需要了解的CSS原理
    第 10 章 文件系统及实现
    第 9 章 虚拟内存管理
    第 8 章 内存管理策略
    第 7 章 死锁
    第 6 章 同步
  • 原文地址:https://www.cnblogs.com/zcsor/p/6305636.html
Copyright © 2020-2023  润新知