题目大意:就是要布场的时候需要挂彩灯,彩灯挂的高度满足:
H1 = A
Hi = (Hi-1 + Hi+1)/2 - 1, for all 1 < i < N
HN = B
Hi >= 0, for all 1 <= i <= N
现在已知彩灯的个数和第一个彩灯挂的高度,要你求最后一个彩灯最低能挂多高?
这又是个最大化最小值的问题,从题目中我们可以看到递推公式的影子,其实这一题我们只要把答案二分,然后根据递推公式写出通项公式,一个灯一个灯看是否有低于0的高度就好
递推公式转通项公式,这一题可以直接看出来,移项我们就可以得出
A(i)-A(i-1)=A(i-1)-A(i)-2
两边同时加上-2i可得,
A(i)-A(i-1)-2i=A(i-1)-A(i)-2(i-1)
也就是A(i)-A(i-1)-2i=C
移项就可以得出变等差公式的递推,最后解得:
A(i)=C*(i-1)+i*(i-1)+A(1)
现在A1是已知的,我们只用不断二分枚举A(i)得到常数C,然后一个一个数看是否有小于0的即可
#include <iostream> #include <algorithm> #include <functional> using namespace std; bool Solve(const double, const double, const int); int main(void) { int lamps_sum; double A_height, mid, lb, ub; while (~scanf("%d%lf", &lamps_sum, &A_height)) { lb = 0; ub = (double)INT_MAX; for (int i = 0; i < 100; i++)//100次的精度很高了 { mid = (ub + lb) / 2; if (Solve(A_height, mid, lamps_sum)) ub = mid; else lb = mid; } printf("%.2f ", lb); } return EXIT_SUCCESS; } bool Solve(const double A1, const double x, const int num_sum) { //递推公式通项:Ai = C*(i - 1) + i*( i - 1 ) +A1 double C = (x - A1 - num_sum*(num_sum - 1)) / (num_sum - 1); for (int i = 1; i <= num_sum; i++)//所有的灯都要触地以上 if (C*(i - 1) + i*(i - 1) + A1 < 0) return false; return true; }