POJ - 1905 Expanding Rods (数学+二分)

6 篇文章 0 订阅

原题地址:
POJ-1905

题意解释:
一个钢管受热发生膨胀伸长。由于墙壁挤压,钢管发生形变而弯曲。计算弯曲后的钢管中心距原中心的距离。

题目吐槽:
一个钢管感到自身浑身燥热于是变长了(竟然还能用公式计算出来多长!),于是它弯了。。。弯。。。了。。。

解决方案:
由题知钢管膨胀后长度的计算公式:L’ = (1+N*C)*L
(L:原长; N:温度差; C:膨胀系数)
分析知形变后的钢管是一个圆的一个劣弧
(输入数据保证钢管膨胀没有超过其原来长度的一半)
形变后的钢管中心在劣弧的中点
画图(假设这里有个图)可知,如果知道圆的半径,就可以通过弦长求圆心到弦的距离,继而求出两中心之间的距离。
那么引出数学公式:L’ = arcsin(L/(2*r))*2*r
(L’:弧长; L:弦长; r:半径)
图片来自百度知道

然后!!
唯一不知道的就是半径了!!我们二分答案!!
最小值是原长的一半(即钢管膨胀为一个完美的半圆)
最大值是50*(L/2)*(L/2)(中心的距离为0.0001时的半径)
每次二分的时候取中间值,
监测此中间值计算出的弧长与标准弧长的差距
如果差距小于零,令最大值等于中间值,否则令最小值等于中间值
当误差小于10^(-4)就可以停止了,此时的中间组织就是我们想要的半径了。
然后再通过公式计算得到两个中心之间的差距。

如果精度不够什么的。。。
调高点也可以。。。
小数点什么的有点玄学。。。
尤其是在没有插件的时候。。。

贴上自己的代码:

#include<iostream>
#include<cmath>
#include<iomanip>
#include<algorithm>
using namespace std;
double core(double L,double N,double C){
    if(N==0){
        return 0;
    }
    double LL;
    LL=(1+N*C)*L;
    double mmin,mmax,mid,dl=-1;
    mmin=L/2;
    mmax=50*(L/2)*(L/2);
    mid=mmax;
    while(abs(dl)>0.00001){
        if(dl<0){
            mmax=mid;
        }else{
            mmin=mid;
        }
        mid=(mmax+mmin)/2;
        if(L/(2*mid)>1){
            dl=1;
            continue;
        }
        dl=asin(L/(2*mid))*2*mid-LL;
    }
    return mid-pow(mid*mid-(L/2)*(L/2),0.5);
}
int main(){
    double L,N,C;
    while(cin>>L){
        if(L<0){
            return 0;
        }
        cin>>N>>C;
        cout<<setiosflags(ios::fixed)<<setprecision(3)<<core(L,N,C)<<endl;
    }
    return 0;
}
//Designed by wolf
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值