2018蓝桥杯省赛C/C++ B组 螺旋折线(题目+题解)

题目:

         如图p1.png所示的螺旋折线经过平面上所有整点恰好一次。  
        对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。 
        例如dis(0, 1)=3, dis(-2, -1)=9 
        给出整点坐标(X, Y),你能计算出dis(X, Y)吗?
【输入格式】
X和Y 
对于40%的数据,-1000 <= X, Y <= 1000  
对于70%的数据,-100000 <= X, Y <= 100000  
对于100%的数据, -1000000000 <= X, Y <= 1000000000 
【输出格式】
输出dis(X, Y) 

【样例输入】
0 1
【样例输出】
3

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms

解题思路:

    看到这道题时发现,其可以看作是 以原点为质心的缺一个角的正方形构成,那么每个点的位置与dis一定是有函数关系的。

    最适合寻找函数关系的点:第一象限内满足y=x的点(因为最特殊,又非负方便计算),写出x、y、dis的关系:

    dis(1, 1) = 2 + 1 + 1;       dis(2, 2)=4 + 3 + 3 + 2 + 2 + 1 + 1;      dis(3, 3) = 6 + 5 + 5 + 4 + 4 + 3 + 3 + 2 + 2 + 1 +1;

    即第一个加数为2i,只出现一次,而后递减的值,都出现两次。

    得出结论: dis(i, i) = (2 * n + 2 * (n-1) + …… + 2 + 2 + 1 + 1) = 4 * i * i;
    
    那么余下的点,皆可以根据与(i, i)的相对关系得出,划分的方式不唯一,以下是我的划分:


根据划分,代码如下

int dis(int x, int y)
{
	int r; // 正方形边长的一半
	if (x == y && x >= 0)return 4 * x * x; // 1. y=x线上,x非负
	if (y > 0) // 2. x轴上方的,延长到右上角
	{
		r = abs(x) > abs(y) ? abs(x) : abs(y);
		return 4 * r * r - abs(x - r) - abs(y - r); // 减去延长部分
	}

	if (y == 0) // 3. x轴上的(除原点)
	{
		r = abs(x);
		if (x > 0)return 4 * r * r + r;
		return 4 * r * r - 3 * r;
	}

	if (y < 0) // 4. x轴下方的,分为左侧竖直(有倒钩)和右下(无倒钩)
	{
		if (y <= x + 1) // 4.1 右下(无倒钩)
		{
			if (y == x + 1)r = 0 - y;
			else r = abs(x) > abs(y) ? abs(x) : abs(y);
			return 4 * r * r + abs(x - r) + abs(y - r);
		}
		if (y > x + 1) // 4.2 左侧竖直(有倒钩)
		{
			return 4 * r * r + (2 * r) + (2 * r + 1) + (y - (-r));
		}
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值