枚举左边的灯塔的高度,二分得到右边的灯塔最低是多少,并更新最小值。
二分中的check用相似三角形算出每两个居民楼之间的两个灯塔没有照射到的部分是否超过了100m.具体的见代码注释.
#include <bits/stdc++.h>
using namespace std;
int a[105];
int n;
int main() {
cin >> n;
int mx = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
mx = max(mx, a[i]);
}
double ans = 1e9;
for (double x = mx; x <= 1e4; x += 0.5) { //枚举左边的灯塔高度
double L = mx, R = 2e5, mid; //二分右边的灯塔高度
for (int i = 1; i <= 30; i++) { //浮点数二分指定次数,此时误差在2e5/(2^30)以内
mid = (L + R) / 2;
bool ok = true;
for (int j = 1; j < n; j++) { //依次判断每两个居民楼之间的间隔是否都照射到
double t = (a[j] * j * 100) / (x - a[j]); //计算左边的灯塔没照射到的部分
t += (a[j + 1] * (n - j) * 100) / (mid - a[j + 1]); //右边的
if (t > 100) { //如果加起来超过100,说明有阴影部分
ok = false;
break;
}
}
if (ok) { //如果当前灯塔mid可以,说明最低的灯塔在[L,mid]的部分,将R置为mid
R = mid;
} else { //反之是[mid,R],将L置为mid
L = mid;
}
}
ans = min(ans, x + mid); //最后用x+mid更新答案
}
cout << int(ans + 0.5); //+0.5再舍去小数位,即四舍五入
}
n = int(input())
a = list(map(int, input().split()))
m = max(a)
f = m+0.5
ans = 100000
while f < 10**4: #枚举左边的灯塔高度
L, R = m, 10000 #二分右边的灯塔高度
for x in range(20): #浮点数二分指定次数,此时误差在1e5/(2^20)以内
mid = (L+R) / 2
for i in range(n-1): #依次判断每两个居民楼之间的间隔是否都照射到
s1 = a[i] * (i+1) * 100 / (f - a[i]) #计算左边的灯塔没照射到的部分
s2 = a[i+1] * (n-i-1) * 100 / (mid - a[i+1]) #右边的
if s1 + s2 > 100: #如果加起来超过100,说明有阴影部分
L = mid #此时灯塔高度不够,说明答案应该在[mid,R],将L置为mid,退出循环
break
elif i == n-2: #如果循环即将结束,说明答案在[L,mid]的部分,将R置为mid
R = mid
ans = min(ans, f+R)
f += 0.5
print(int(ans+0.5)) #+0.5再舍去小数位,即四舍五入
小红住的小区前面有一条公路,在公路上有一排 n 个居民楼,每个居民楼都有一个高度,第 i 个居民楼的高度为 ai ,相邻居民楼都相隔 100 米,小红最近回家的时候经常没有路灯,然后经常迷路,现在小红想在想要是公路左右两边各设计一座灯塔,这样灯塔就可以把所有地方都照亮,小红回家路上就不会迷路了,现在小红想知道灯塔至少得有多高。
为了简化问题,公路可看做一条直线, 居民楼和灯塔可看做立在公路旁边的一条竖线,左边的灯塔距离最左边的居民楼和右边灯塔距离最右边的居民楼也都是 100 米。居民楼会挡住灯光,如果从最左边的居民楼到最右边的居民楼中间的点都要至少要被一座灯塔照亮, 那么两座灯塔高度之和最少是多少。
第一行输入 N ( 2≤N≤100 ),代表居民楼数量
第二行有 N 个整数,第 i 个整数代表从左到右第 1 座居民楼的高度,居民楼高度在 [1,100] 米范围内
输出从最左边的居民楼到最右边的居民楼中间的点都要至少要被一座灯塔照亮, 所需要的两座灯塔高度之和的最小值,值为整数。
输入
2
100 100
输出
600
输入
3
100 90 80
输出
738