题目传送门在此
似乎是道纯几何题,图解如下,这样子摞出来的一堆圆,给出最下一层的所有圆心的横坐标,半径均为1,要求出最顶端的圆的圆心
每一层比下一层少一个,也就是下层每两个夹一个,我们可以看出下两个和上一个的圆心组成一个腰为2的等腰三角形。可以根据下两个的坐标推出一个几何关系。
定义一个坐标结构体方便计算,算坐标的函数写得略臃肿,不过是根据推断过程一步步来的.
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
struct coordinate {
double x;
double y;
};
bool cmp(const coordinate& c1, const coordinate& c2) {
return (c1.x < c2.x);
}
coordinate cal(coordinate c1, coordinate c2) {
double x1 = c1.x;
double x2 = c2.x;
double y1 = c1.y;
double y2 = c2.y;
double midX = (x1 + x2) * 0.5;
double midY = (y1 + y2) * 0.5;//中点
double k = (y1 - y2) / (x1 - x2);//下两点连线斜率
if (y1 == y2) {
coordinate result;
result.x = midX;
double height = sqrt(4 - (fabs(x2 - x1) * 0.5) * (fabs(x2 - x1) * 0.5));
result.y = y1 + height;
return result;//持平就直接算
} else {
k = -1.0 / k;//算垂直平分线斜率
double len = sqrt(16.0 - (y1 - y2) * (y1 - y2) - (x1 - x2) * (x1 - x2)) * 0.5;
double vx, vy;
if (k < 0.0) {
vx = -1.0 / sqrt(k * k + 1);
vy = -k / sqrt(k * k + 1);
} else {
vx = 1.0 / sqrt(k * k + 1);
vy = k / sqrt(k * k + 1);
}
vx *= len;
vy *= len;//算中点指向目标点的向量坐标
double tarX = midX + vx;
double tarY = midY + vy;
coordinate result;
result.x = tarX;
result.y = tarY;
return result;
}
}
int main() {
int n;
while ((cin >> n) && n) {
coordinate all[11];
for (int i = 0; i < n; ++i) {
cin >> all[i].x;
all[i].y = 1.0;
}
sort(all, all + n, cmp);
int k = n;
while (k > 1) {
for (int i = 0; i < k - 1; ++i) {
all[i] = cal(all[i], all[i + 1]);
}
--k;
}
printf("%.4f %.4f\n", all[0].x, all[0].y);
}
return 0;
}