螺旋困境(模拟)

15 篇文章 0 订阅

题干

小W是一个宅男,喜欢发呆,并幻想一些不切实际的事情。今天,小W又开始做他的白日梦了。他梦见他被困在了一条隧道里,周围漆黑一片。作为一个宅男,小W自然地掏出了手机,打开定位系统,确定了他的位置。又由此在网上搜索到了关于隧道的信息。这条隧道是由一个点向外,呈六角螺旋形展开,并且没有其他的支路。最小的一圈每条边的长度都是1米,边长向外依次增大到2,3...米,如下图所示。

输入数据以一个整数T<104开头,表示测试数据组数。以下每行为一组测试数据,包括4个整数X1,Y1,X2,Y2,描述了小W所在的位置和出口位置的坐标。所有坐标的绝对值不超过1018,并保证答案不超出64位有符号整数的表示范围。

输出对于每组测试数据输出一行,一个整数,表示小W所在的位置和出口的距离。

 

Sample Input

2
1 0 0 1
1 1 2 0

Sample Output

2
9

分析

模拟题,我的方案是先计算起点和终点所在的层数,每层的长度是一个公差为6的等差数列,考虑数列求和公式。
这里要考虑两种情况。
第一种情况:起点为(0,0),终点为任意。先用求和公式计算终点所在圈以内所有圈的长度总和,然后加上终点所在圈的位置长度,终点的位置长度至少要分4种情况。
第二种情况:起点任意,终点在起点以外的任意位置,先求起点和终点之间圈的长度总和,然后加上终点所在圈的距离,加上起点所在该圈的长度,再减去起点所在圈的位置长度。
注意:本题起点和终点是可以对换位置的,若是对换位置,则上面方法的计算结果为负数,需要取绝对值(不能用abs,abs只适用于int)。

各圈分解见下图所示,同色代表为同一圈

 

题解

#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
ll count_layer(ll x,ll y,ll layer){
    if(x<0&&y==0) return 0;
    else if(x<=0&&y<0){
        if(x<=y){
            return -1*y;
        }
        else{
            return layer*2+x;
        }
    }
    else if(x>0&&y<=0) return layer*3+y;
    else{
        if(y<=x){
            return layer*3+y;
        }
        else{
            return layer*5-x;
        }
    }
}
int main(){
    ll T;
    cin>>T;
    ll i;
    for(i=0;i<T;++i){
        ll x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        ll absx1 = x1>0 ? x1:-1*x1;
        ll absy1 = y1>0 ? y1:-1*y1;
        ll absx2 = x2>0 ? x2:-1*x2;
        ll absy2 = y2>0 ? y2:-1*y2;
        ll layer_position = absx1>absy1 ? absx1:absy1;
        ll layer_outlet = absx2>absy2 ? absx2:absy2;
        if(x1>0&&y1<0) layer_position = absx1+absy1;
        else if(x1<-1&&y1>0) layer_position =absx1+absy1-1;
        if(x2>0&&y2<0) layer_outlet = absx2+absy2;
        else if(x2<-1&&y2>0) layer_outlet =absx2+absy2-1;
        if(layer_position==layer_outlet&&layer_position==0){
            cout<<0<<endl;
        }
        else if(layer_position==0&&layer_outlet>0){
            ll n = layer_outlet-1;
            ll ans = 7*n+n*(n-1)*3+1;
            ans+=count_layer(x2,y2,layer_outlet);
            ans>0 ? ans:-1*ans;
            cout<<ans<<endl;
        }
        else{
            ll n2 = layer_outlet-layer_position-1;
            ll ans1 = (6*layer_position+1)- count_layer(x1,y1,layer_position);
            ll ans2 = ((layer_position+1)*6+1)*n2+n2*(n2-1)*3+count_layer(x2,y2,layer_outlet);
            ans2+=ans1;
            ans2 = ans2>0 ? ans2:-1*ans2;
            cout<<ans2<<endl;
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值