您的位置:首页 > 其它

POJ 1759 Garland 二分答案

2016-06-28 15:38 375 查看

题意

题目背景是在绳上挂灯。。我觉得完全不用鸟这个背景。。。

它表达的核心意思,就是一个数列告诉你首项h1, 项数n,递推式hi = (hi+1 + hi-1 ) / 2 - 1

在保证hi都大于等于0的前提下,让hn最小

思路

这题不难想到可以使用二分,但是二分哪个变量,找到哪样的单调关系需要考虑一下。

首先,通过题目给出的递推式,很容易得到标准的递推形式: hi+1 = 2hi - hi-1 + 2

这样,我们就知道,只要确定了h2,hn肯定就确定了,所以我们二分的变量就是h2了

接下来,我们从递推式入手,来找单调关系

假如递推式为:hi = (hi+1 + hi-1 ) / 2,那会有怎样的结果呢?不难想象,当h2确定时,整个数列就是一个等差数列了,所以数列肯定是单调的。

而如果hi在这个基础上减一呢?不难想象,在hi+1 < hi-1时,hi位于两个数等分位偏hi+1的位置一些,而在hi+1 > hi-1时,hi位于两个数等分位偏hi-1的位置一些。所以在h2 < h1的情况下,整个数列画出的图像一定是先单调递减,但递减幅度越来越小,直至幅度减到足够小,然后递增,并且递增幅度越来越大的过程。

因此,我们的单调关系就是,f(h2): hi是否都大于等于0

另外,这个递推式,通过迭代几次找规律的方法,也不能得出通项公式,不过这个通项公式并不影响整体复杂度,所以这里不多提了,代码里用了一下~

注意:poj上如果用g++,输出不能用%lf,否则WA,要用%f。这个原因我也不是很明白,如果有路过的大神,也望指点一下~~

实现

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int n;
double A;
const double eps = 1e-6;
bool judge(double a1, double a2){
for (int i=3;i<=n;i++){
a1 = 2 * a2 - a1 + 2;
if (a1 < 0)
return false;
swap(a1, a2);
}
return true;
}
int main(){
cin>>n>>A;
double l = 0, r = A, a = 0;
int T = 100;
while (T--){
double mid = (r+l) / 2;
if (judge(A, mid)){
r = mid;
a = mid;
}
else{
l = mid;
}
}
double a1 = A, a2 = a;
printf("%.2f\n",(n-1) * a2 - (n-2) * a1 + (n-1) * (n-2));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 二分答案 acm 算法