poj 1905 Expanding Rods

点击打开链接poj1905


思路:二分
分析:
1 题目要求的是找到变形后的弧和原来的弦中心的距离ans
2 很明显的数学题,题目明确告诉我们变形后的增加弧长不会大于L/2,那么我们就可以确定ans的范围[0,L/2),那么我们就可以对ans进行二分,然后利用三角形的勾股定理求出半径r,求出了半径我们可以求出圆心角,然后进一步求出弧长,最后和newLen(最终变形后的长度)进行比较;
3 很明显这一题的精度要求很高。如果我们还是利用while(left - right < eps){} 这样肯定是不行的,当left无限接近去right的时候将陷入无限循环或者是得到不够准确的答案,所以这里我们改成while(right-left > eps){}这样我们就可以得到准确的答案;还有在确定left 和 right的时候不再是left = mid+1,而是利用left = mid,然后不断的逼近求出最后的ans即为left。
4 注意数据就是三个数里面只要有一个为0,那么ans肯定是0,不用进行二分。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

#define eps 1e-8

int n;
double len , c , newLen;

void solve(){
   double left , right , mid , tmp , ans;
   
   newLen = (1+n*c)*len;/*最终变形后的长度*/
   tmp = (len/2)*(len/2);
   left = 0 , right = len/2;/*二分的上下界*/

   while(right - left >  eps){
      mid = (right+left)/2;
    
      double r = (mid*mid+tmp)/(2*mid);/*求出半径*/
      double tmpLen = asin((len/2)/r)*2*r;/*求出弧长*/
      
      if((tmpLen-newLen) > eps)
         right = mid;
      else
         left = mid;
   }
   printf("%0.3lf\n" , left);
}

int main(){
   while(scanf("%lf%d%lf" , &len , &n , &c)){
      if(len < 0 && n < 0 && c < 0)
        break;
      if(len == 0 || n == 0 || c == 0)/*特殊处理*/
        printf("0.000\n");
      else
        solve();
   }
   return 0;
}





你可能感兴趣的:(poj 1905 Expanding Rods)