Expanding Rods POJ1905 二分
http://poj.org/problem?id=1905
这个题目其实想到了方法一点都不难,但是一般想到方法也不过是找到了一个关于r和sita的表达式,然后进行行二分或三分求解。
所以一般的求解显得复杂,参考了大神的解法之后,真心觉得ACM算法之路好有好长。
简述一下大神的做法:
大神选择了直接二分高度,通过高度和弦长推出半径,再算角度,最后与实际的弧长进行比较,并最后进行调整。
这种算法的好处有以下几点;
1.使用相交弦定理,一步求出半径(真不知大神怎么还会记得相交弦定理啊,这数学基础!!!!!)
2,只在求sita时使用了一次反三角函数,不像其他的算法,反复的求三角正弦,余弦啊各种·····尽量保留了精度。
3,突破以往的二分模式,并不求关于高度的calcu表达式,而是间接利用,以判断大小
4,最后,我觉得最神奇的是大神在复杂的题意下,找到了一个非常简洁的单挑函数:依题长度增加做多不过一半,也就是其形成的扇形组最大不过是半圆,那么在弦长一定的时候,给一个弧高就可以确定一个园,进而可以确定这段弧长。
反正我自己觉得这个算法很牛,不知读者怎么想,再次表达一下对这些大神们神一样的解题思路的无限敬仰。
这是我按照思路,自己写的代码,读者应该能写出更好的:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 using namespace std; 5 #define eps 1e-4 6 double l,c,ls,n,r,sita; 7 double solve(double a,double b) 8 { 9 double left,right,mid; 10 left=a; 11 right=b; 12 while(left+eps<right) 13 { 14 15 mid=(left+right)/2; 16 r=l*l/8/mid+mid/2; 17 //sita = acos(1-l*l/r/r/2); 18 sita=2*asin(l/2/r); 19 if(sita*r>=ls) 20 right=mid; 21 else 22 left=mid; 23 } 24 return left; 25 } 26 int main() 27 { 28 while(~scanf("%lf%lf%lf",&l,&n,&c)) 29 { 30 if(l<0||n<0||c<0)break; 31 ls=l*(1+n*c); 32 printf("%.3f\n",solve(0,l/2)); 33 } 34 return 0; 35 }
posted on 2013-08-08 13:24 plank george 阅读(375) 评论(0) 编辑 收藏 举报