题目描述
小姬最近开始研究起了曼哈顿距离,因为他厌倦了欧氏距离的学习。
我们知道,平面内 (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;
}