回形遍历 calc

传送

70分,N^2的时间复杂度,模拟呗。
只是变量好繁琐,以及这个题本身烦人的坐标倒置。

100分,也是模拟,不过要在70分的基础上加上优化,70分每次只走一个格,而100分时优化到每次走一排(或者一列)。O(4*n)
实现:
观察下面的图:
这里写图片描述
发现,除了第一次,其他时候dx和dy都要-1

70分

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
int ax,ay,n,m,x,y,z,q;
int f[1009][1009],flag;
int main()
{
    scanf("%d%d%d%d%d",&n,&m,&x,&y,&z);
    //q=min(min(n-x,m-y),min(x+1,y+1));
    //printf("%d",q);//第几圈
    int p=m*n,num=0,dir=1;
    ax=1,ay=1; 
    x++,y++;
    while(num<p)
    {
        //printf("(%d,%d)\n",ax,ay); 
        if(!f[ay][ax]) f[ay][ax]=++num;

        if(ax==x&&ay==y) p=num+z;//走到(x,y)再走z步 

        if(dir==1)//右 
        {
            ax++;
            if(ax>n||f[ay][ax]!=0) 
            {
                ax--,dir=2;//下 
            }
        }
        else if(dir==2)//下 
        {
            ay++;
            if(ay>m||f[ay][ax]!=0) 
            {
                ay--,dir=3;//左 
            }
        }
        else if(dir==3)//左 
        {
            ax--;
            if(ax<1||f[ay][ax]!=0) 
            {
                ax++,dir=4;//上
            } 
        } 
        else if(dir==4)//上 
        {
            ay--;
            if(ay<1||f[ay][ax]!=0) 
            {
                ay++,dir=1;//右 
            }
        }

    }
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(f[i][j]==p)
            {
                printf("%d %d",j-1,i-1);//一开始不想这样找最后的坐标,无奈老是错,只好这样
                return 0;
            }   
        }

    }
    return 0; 
}

100分

#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<cstdio> 
#define LL long long
using namespace std;
LL n,m,x,y,deep,dir,ax,ay,first=1;
LL z,step,maxn;
int main()
{
    //freopen("a.in","r",stdin);
    scanf("%lld%lld%lld%lld%lld",&n,&m,&x,&y,&z);
    dir=1;step=1;maxn=1ll*(n*m);
    LL dx=n-1,dy=m-1;
    while(step!=1ll*(n*m))
    {
        if(dir==1)
        {
            if(ay==y&&ax<=x&&ax+dx>=x)
            {
                maxn=step+(x-ax)+z; 
            }

            step+=dx;
            ax+=dx;

            if(step>=maxn)
            {
                printf("%lld %lld",ax-(step-maxn),ay);
                return 0;
            }

            dir=2;
            if(!first) dx--;//除了第一圈,dx--
            else first=0;
        }
        else 
        if(dir==2)
        {
            if(ax==x&&ay<=y&&ay+dy>=y)
            {
                maxn=step+(y-ay)+z; 
            }

            step+=dy;
            ay+=dy;

            if(step>=maxn)
            {
                printf("%lld %lld",ax,ay-(step-maxn));
                return 0;
            }

            dir=3;
            dy--;
        }
        else
        if(dir==3)
        {
            if(ay==y&&ax>=x&&ax-dx<=x)
            {
                maxn=step+(ax-x)+z; 
            }

            step+=dx;
            ax-=dx;

            if(step>=maxn)
            {
                printf("%lld %lld",ax+(step-maxn),ay);
                return 0;
            }

            dir=4;
            dx--;
        }
        else 
        if(dir==4)
        {
            if(ax==x&&ay>=y&&ay-dy<=x)
            {
                maxn=step+(ay-y)+z; 
            }

            step+=dy;
            ay-=dy;

            if(step>=maxn)
            {
                printf("%lld %lld",ax,ay+(step-maxn)); 
                return 0;
            }

            dir=1;
            dy--;
        }
    }
    printf("%d %d",ax,ay);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值