YTU 3413: 小姬小姬小姬

题目描述

小姬最近开始研究起了曼哈顿距离,因为他厌倦了欧氏距离的学习。

我们知道,平面内 (x1,y1) 与 (x2,y2) 的曼哈顿距离被定义为这两点在标准坐标系上的绝对轴距之和,即 |x1−x2|+|y1−y2|。

对于小姬来讲,他可以很容易的算出给定平面内任意多个点之间的曼哈顿距离,但是千千给小姬出了一个问题:假如我有 n(n−1)2 个数,它们分别代表平面中 n 个点之间的曼哈顿距离,你能告诉我这 n 个点的位置么?

随后的几天,小姬开始困惑了,因为他想来想去也只会算当 n=2 的情形,于是便去找千千诉苦,看到这样的情形,千千只好答应降低难度,只要你算出 n=3 的情形便可以啦。

你能帮小姬解决这个问题么?

输入

输入只有一行,包含三个正整数 a,b,c (1≤a,b,c≤100),分别代表平面中 3 个点两两之间的曼哈顿距离。(保证输入数据有解)

输出

输出满足题意的三个点的坐标(要求 0≤|x|,|y|≤105),每个点的坐标占一行,可以以任意的顺序输出,若存在多解的情况,输出任意一组即可。(如果你的答案计算出的结果与真实值相差 10−6 以内则被认为是正确的)

样例输入

1 1 2

样例输出

0.000000 0.000000
1.000000 0.000000
0.000000 1.000000

思路

在这三个曼哈顿距离中任取一个d,它一定表示两点之间的曼哈顿距离
设其中一个点为原点,则另一个点一定在以原点为中心距离远点曼哈顿距离为d的菱形(正方形)上。
其他两个输入值,其中有一个值是于原点相关的曼哈顿距离,而这个值对应的点也应该是围绕原点的一个菱形(正方形)

不妨先假设其中一个值是与原点相关的曼哈顿距离,只要第三个值(原点除外的其他两点的曼哈顿距离)在区间【两菱形之间点的最短距离,两菱形点的最长距离】范围之内,则必定可以求解,如果不满足,则最后剩下的值才是与原点关联的值

这样我们就可以先直接定死两个点,求第三个点。
先说两个菱形大小不一样的情况:
如下图,(这个图我只看了右边)
1.我定的点是(0,0)和小菱形最上端的点(0,x)
图中上方表示红线(0,x)和求解点有最短距离时求解点存在的范围,在这一线段上(0,x)和求解点的曼哈顿距离相等,这个最短距离为abs(与原点相关的连个曼哈顿距离只差),若不关联原点的曼哈顿距离就是最短距离,则随便取红线上的一点就是答案
2.同理,下方红线表示(0,x)和所求点曼哈顿距离最长的范围,若不关联原点的曼哈顿距离等于最长距离,则随便在下方红线上取一点就是答案
3.在蓝线上(0,x)到求解点的曼哈顿距离递增
我们可以先把求解点定在上方红线的最下边,这时求解点与(0,x)的曼哈顿距离为最短距离,然后再将求解点向下偏移,令两点之间的曼哈顿距离增长(不关联原点的曼哈顿距离-最短距离),得到的点就是答案(斜率都是1或-1呀)
在这里插入图片描述
如果两个菱形大小一样,最上方的红线就会变成一个点,其余思路不变,所以这种情况不用另外考虑 战吼:放一个P

代码

一遍过的,里面有些冗余的东西写出来了根本没用上,比如那个结构体的点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>

struct Edge
{
    float x,y;
}p1,p2,p3;
int a,b,c;

void fun(float p,float q,float w)
{
    float x,y,px,py,left;
    if(p<q) x=p,y=q;
    else x=q,y=p;
    if (w == std::abs(p-q))
    {
        px=0;
        py=y;
    }
    else if(w == p+q)
    {
        px=0;
        py=-y;
    }
    else
    {
        float tmp=std::abs(p-q);
        px=tmp,py=x;
        left=w-tmp;
        left/=2;
        px+=left;
        py-=left;
    }
    printf("%.6f %.6f\n",0.0,0.0);
    printf("%.6f %.6f\n",0.0,x);
    printf("%.6f %.6f\n",px,py);


}

int main()
{
    std::cin >> a >> b >> c;
    p1.x=p1.y=0;
    if(c>= std::abs(a-b) && c<= a+b)
    {
        fun(a,b,c);
    }
    else
    {
        fun(a,c,b);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值