UVALive-7528-Beehive

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5550

求 i 到 j 的最短距离

坐标系建立:   y轴正常建,x轴分成两部分,x<0时x轴平行于5->3的方向,x>0时x轴平行于3->11的方向

原来每一层是这样

12 13 14 15 16 17 18 19 20

     05 06 07 08 09 10 11

               02 03 04

                    01 (第一层)

我们发现当层数 i 为奇数时,num【i】= num【i-1】+4,偶数时num【i】= num【i-1】+2

按正常坐标轴展开后是这样

     89 68 50 35 23 24 25 26 27 28 29 30 31 47 66 88 113

               49 34 22 13 14 15 16 17 18 19 32 48 67

                         21 12 06 07 08 09 1020 33

                                   05 02 03 04 11

                                             01 (第一层)

第 i 层两端各有(i-1)/2个元素的位置改变

这样每一个数的坐标就都可以得到了

接下来求两个点(x,y)和(xx,yy)之间的距离

当x<=0时,(x,y)到(x+1,y-1)只需要一步

当 x>0 时,(x,y)到 (x-1,y-1)只需要一步

其他的改变需要fabs(x-xx)+fabs(y-yy)步

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <queue>
#include <vector>
#include <math.h>
#include <stack>
#include <map>
#include <set>
#define rtl rt<<1
#define rtr rt<<1|1
typedef long long LL;
using namespace std;
const int mod = 1e9+7;
const int MAX = 1e6+10;
const double eps = 1e-10;
const double PI = acos(-1.0);
int x, y, xx, yy, a, b, ans;
struct node
{
    int l, r, mid, p;
} lxt[100];
void f(int n, int &x, int &y)
{
    if(n==1)
    {
        x = 0;
        y = 1;
    }
    else
    {
        int k;
        for(k = 2; k<=82; ++k)
            if(lxt[k].l<=n&&lxt[k].r>=n)break;
        y = k;
        if(n<lxt[k].l+lxt[k].p)
        {
            y-=lxt[k].l+lxt[k].p-n;
            x = lxt[k].l-lxt[k].mid+lxt[k].p;
        }
        else if(n>lxt[k].r-lxt[k].p)
        {
            y-= n-lxt[k].r+lxt[k].p;
            x = lxt[k].r-lxt[k].mid-lxt[k].p;
        }
        else x = n-lxt[k].mid;
    }
}
void dis()
{
    if(x>xx)
    {
        swap(x, xx);
        swap(y, yy);
    }
    while(x<xx&&y<yy)
    {
        if(xx<=0)ans+=2;
        else ans+=1;
        yy--;
        xx--;
    }
    while(x<xx&&y>yy)
    {
        x++;
        y--;
        if(x<=0)ans+=1;
        else ans+=2;
    }
    ans+=fabs(yy-y)+xx-x;
}
int main()
{
    lxt[1].l = lxt[1].r=lxt[1].mid = 1;
    lxt[1].p = 0;
	for(int i = 2; i<=82; ++i)
    {
        lxt[i].l = lxt[i-1].r+1;
        lxt[i].r = lxt[i].l+lxt[i-1].r-lxt[i-1].l+(2<<(i&1));
        lxt[i].mid = (lxt[i].l+lxt[i].r)>>1;
        lxt[i].p = max(0, (i-1)/2);
    }
    while(~scanf("%d%d", &a, &b))
    {
        if(!a&&!b)break;
        f(a, x, y);
        f(b, xx, yy);
        ans = 0;
        dis();
        cout<<ans<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值