P7002
题目
有
给出最大的长度之和,并构造方案。
分析
显然可以将最后一个被照到光的塔移到折线的某个端点上使得答案不变劣,不妨设这个塔编号为
考虑将所有塔被光照到的部分沿着光线平移至
对于求答案,可以发现上式
对于构造方案,上面已经说了,确定了最高点后,贪心的在最高点前填使得被光照到的地方尽可能多,然后再尽可能靠前。可以直接在
于是不难做到
代码
typedef long double ff;
const int N = 1e4 + 5;
const ff PI = acos(-1), EPS1 = 1e-20, EPS2 = 1e-6, INF = 1e20;
int n, m, h[N], X[N], Y[N]; ff alpha, pos[N];
ff GetHeight(int i) { return (X[i] - X[1]) * tan(alpha) + (Y[i] - Y[1]); }
ff Ints(int x_0, int y_0, int i) {
ff k_1 = (Y[i + 1] - Y[i]) / (ff)(X[i + 1] - X[i]), k_2 = -tan(alpha),
b_1 = -k_1 * X[i] + Y[i], b_2 = -k_2 * x_0 + y_0;
return (b_2 - b_1) / (k_1 - k_2 + EPS1);
}
bool Check(int x_0, int y_0, int i) {
ff x_ints = Ints(x_0, y_0, i);
return x_ints > X[i] - EPS2 && x_ints < X[i + 1] + EPS2;
}
int main() {
rd(n, m, alpha); alpha *= PI / 180;
int h_sum = 0, h_mx = 0, h_mx_id = 0;
for(int i = 1; i <= n; ++i) {
rd(h[i]); h_sum += h[i];
if(h[i] > h_mx) {
h_mx = h[i];
h_mx_id = i;
}
}
for(int i = 1; i <= m; ++i) rd(X[i], Y[i]);
ff ans = -INF;
for(int i = 1; i <= m; ++i) {
ff i_h = GetHeight(i);
if(i_h > ans) {
ans = i_h;
pos[h_mx_id] = X[i];
}
}
ans += h_mx;
ans = std::min(ans, (ff)h_sum);
int cur_y = Y[1];
for(int i = 1, j = 1; i <= n; ++i) {
if(i == h_mx_id) continue;
for(; j < m - 1 && !Check(X[1], cur_y, j); ++j);
pos[i] = std::max(std::min(Ints(X[1], cur_y, j), (ff)X[m]), (ff)X[1]);
cur_y += h[i];
}
printf("%.15LF\n", ans);
for(int i = 1; i <= n; ++i)
printf("%.15LF\n", pos[i]);
return 0;
}