CF 2138F Ode to the Bridge Builder
cnblogs。
非常好几何题。
最后一部分参考了 Milmon 大神的代码,非常感谢!
首先能够发现
又因为题目要求了
并且每一步都能加一个贴着
那么尝试让第一个三角形就贴着
不过这样有个问题就是当
对此,因为
分析对应的步数,能够发现只需要
不过这个构造方法肯定不是通用的,现在只保证了
记
首先来考虑
使用余弦定理:
结合
尝试代入常用角,会发现
于是应当要有
接下来考虑
依然是余弦定理:
首先因为
接下来把
于是只要
那么如果
刚刚的构造其实已经非常好了,我们尝试继续复用这个结构。
因为这个结构只需要满足
具体来说,发现当
如图:
对于
在变化之后,
不过此时有一个问题是,我们多引入了一个三角形。
当
不过当
第一次显然是省不了的,那就只能省掉后面平行四边形的步数了。
不过在叠加的过程,平行四边形的
那么最后也只能尝试在最后
也就是说,当剩下的
首先因为长度
但是这个时候若
此时回归
那还是继续考虑什么情况
确定的是,最后一定会有
于是对于上界,我们只需要考虑
还是余弦定理:
所以这说明
那么会发现取
当
接下来就需要考虑一下
接下来只需要考虑下界的问题了。
- 对于
BC :|BC|^2 = 1 + |AC|^2 - \sqrt{3}|AC| ,对称轴为\frac{\sqrt{3}}{2} ,结合定义域,当|AC| = 1 时取到最小值2 - \sqrt{3} \approx 0.26 \ge \frac{1}{4} 。 - 对于
BD :|BD|^2 = 1 + \frac{1}{4}|AC|^2 - \frac{\sqrt{3}}{2}|AC| ,对称轴为\sqrt{3} ,结合定义域,当|AC| = \sqrt{3} 时取到最小值1 + \frac{3}{4} - \frac{3}{2} = \frac{1}{4} ,甚至刚刚好。
于是对于上述的情况,只需要取
时间复杂度为
#include <bits/stdc++.h>
const double pi = acos(-1);
constexpr int N = 3e5 + 10;
int u[N], v[N];
double sx[N], sy[N];
inline void solve() {
int x, y;
scanf("%d%d%*d", &x, &y);
double d = hypot(x, y);
double th = atan2(y, x);
double sint = 1.0 * y / d;
double cost = 1.0 * x / d;
int a = 1, b = 2, m = 2;
sx[1] = 0.0, sy[1] = 0.0;
sx[2] = 1.0, sy[2] = 0.0;
auto add = [&](double x_, double y_) {
m++;
u[m] = a, v[m] = b;
sx[m] = x_, sy[m] = y_;
return m;
};
if (th > pi / 3) {
b = add(cos(th - pi / 6), sin(th - pi / 6));
}
if (th < pi / 6) {
b = add(cos(th + pi / 6), sin(th + pi / 6));
}
while (d > 2) {
a = add(sx[a] + cost, sy[a] + sint);
b = add(sx[b] + cost, sy[b] + sint);
d -= 1;
}
a = add(sx[a] + d / 2.0 * cost, sy[a] + d / 2.0 * sint);
if ((pi / 6 <= th && th <= pi / 3) || d > 1.5) {
b = add(sx[b] + d / 2.0 * cost, sy[b] + d / 2.0 * sint);
}
a = add(x, y);
printf("%d\n", m - 2);
for (int i = 3; i <= m; i++) {
printf("%d %d %.10lf %.10lf\n", u[i], v[i], sx[i], sy[i]);
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}