您的位置:首页 > 产品设计 > UI/UE

Divide and conquer:Garland(POJ 1759)

2016-01-27 20:25 357 查看
                 


                  挂彩灯

  题目大意:就是要布场的时候需要挂彩灯,彩灯挂的高度满足:


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\n", 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;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: