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; }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法