T247867 05-06-D03-海狸咬树(选做)(L5)
题目描述
# T247867 05-06-D03-海狸咬树(选做)(L5)
## 题目描述
当海狸咬一棵树的时候,它从树杆咬出一个特别的形状。树杆上剩下的部分好像2个圆锥截体用一个直径和高相等的圆柱体连接起来一样。有一只很好奇的海狸它关心的不是要把树咬断,而是想计算出在给定要咬出一定体积的木屑的前提下,圆柱体的直径应该是多少?
如下图所示,假定树杆是一个直径为D的圆柱体,海狸咬的那一段高度也为D。那么给定要咬出体积为V的木屑,内圆柱体的直径d应该为多少?其中D和V都是整数。

图 海狸咬树示意图
## 输入格式
输入数据占一行,为2个整数D和V,用空格隔开。D是圆柱体的直径,V是要咬出的体积。D和V的范围是\[10, 10000]。
## 输出格式
输出占一行,为d的值,保留小数点后3位小数。
## 输入输出样例 #1
### 输入 #1
```
10 250
```
### 输出 #1
```
8.054
```
## 输入输出样例 #2
### 输入 #2
```
20 2500
```
### 输出 #2
```
14.775
```
## 说明/提示
### 提示

### 本题出处
本题源自以下教材的编程习题:王桂平, 周祖松, 穆云波, 葛昌威编著. C++趣味编程及算法入门. 北京大学出版社, 2024年出版.
一、题目分析
题目要求计算海狸咬树时,在给定树杆直径D
和咬出的木屑体积V
的情况下,内圆柱体的直径d
。树杆原本是直径为D
、高度为D
的圆柱体,咬出的形状使得剩余部分由两个圆锥截体和一个直径与高相等的内圆柱体组成,需通过体积关系推导d
的计算公式。
二、核心思路
解决问题的关键是推导 “咬出的木屑体积V
” 与D
、d
的关系公式,步骤如下:
- 计算原树杆(大圆柱体)的体积;
- 计算剩余部分(内圆柱体 + 两个圆锥截体)的体积;
- 利用 “咬出的体积 = 原体积 - 剩余体积” 建立等式,解出
d
。
三、体积公式推导
1. 原树杆(大圆柱体)体积
原树杆是直径D
、高度D
的圆柱体,半径为D/2
,体积公式为:\(V_{\text{原}} = \pi r^2 h = \pi \left(\frac{D}{2}\right)^2 \cdot D = \frac{\pi D^3}{4}\)
2. 剩余部分体积
剩余部分由两部分组成:内圆柱体和两个圆锥截体。
内圆柱体:直径
d
、高d
(直径与高相等),半径d/2
,体积为:\(V_{\text{内圆柱}} = \pi \left(\frac{d}{2}\right)^2 \cdot d = \frac{\pi d^3}{4}\)两个圆锥截体:对称分布在内圆柱体上下,总高度为
D - d
(原高度D
减去内圆柱高度d
),每个截体高度为(D - d)/2
。圆锥截体体积公式为:\(V_{\text{截体}} = \frac{\pi h (r_1^2 + r_1 r_2 + r_2^2)}{3}\),其中:h = (D - d)/2
(单个截体高度),r₁ = d/2
(截体下底半径,与内圆柱半径相同),r₂ = D/2
(截体上底半径,与原树杆半径相同)。
两个截体总体积为:\(V_{\text{截体总}} = 2 \times \frac{\pi \cdot \frac{D-d}{2} \cdot \left( \left(\frac{d}{2}\right)^2 + \frac{d}{2} \cdot \frac{D}{2} + \left(\frac{D}{2}\right)^2 \right)}{3}\)
化简后(利用立方差公式 \(a^3 - b^3 = (a-b)(a^2 + ab + b^2)\)):\(V_{\text{截体总}} = \frac{\pi (D^3 - d^3)}{12}\)
3. 咬出的体积V
的等式
咬出的体积 = 原体积 - 剩余体积(内圆柱 + 截体总):\(V = V_{\text{原}} - \left( V_{\text{内圆柱}} + V_{\text{截体总}} \right)\)
代入化简后最终得:\(V = \frac{\pi (D^3 - d^3)}{6}\)
解此等式求d
:\(d^3 = D^3 - \frac{6V}{\pi} \implies d = \sqrt[3]{D^3 - \frac{6V}{\pi}}\)
四、代码实现步骤详解
1. 引入头文件与命名空间
cpp
运行
#include<bits/stdc++.h> // 包含数学函数pow、输入输出控制等
using namespace std;
2. 定义常量与读取输入
cpp
运行
double pi = 3.1415926; // 定义π的近似值
double D, V; // D:树杆直径;V:咬出的体积
cin >> D >> V; // 读取输入
3. 计算内圆柱体直径d
根据推导的公式计算:
cpp
运行
// 计算三次根号内的表达式:D³ - (6V)/π
double inner = D * D * D - (6 * V) / pi;
// 计算三次方根(pow(x, 1.0/3)表示x的立方根)
double d = pow(inner, 1.0 / 3);
4. 输出结果(保留 3 位小数)
cpp
运行
cout << fixed << setprecision(3) << d << endl;
fixed
:固定小数点后位数;setprecision(3)
:保留 3 位小数。
五、示例测试解析
样例 1 输入:
plaintext
10 250
- 计算过程:\(D³ = 10³ = 1000\),\(6V/π = 6×250 / 3.1415926 ≈ 477.4648\),根号内值 = \(1000 - 477.4648 ≈ 522.5352\),\(d = \sqrt[3]{522.5352} ≈ 8.054\)(与输出一致)。
样例 2 输入:
plaintext
20 2500
- 计算过程:\(D³ = 20³ = 8000\),\(6V/π = 6×2500 / 3.1415926 ≈ 4774.648\),根号内值 = \(8000 - 4774.648 ≈ 3225.352\),\(d = \sqrt[3]{3225.352} ≈ 14.775\)(与输出一致)。
六、完整代码
cpp
运行
#include<bits/stdc++.h>
using namespace std;
int main()
{double pi = 3.1415926; // π的近似值double D, V;cin >> D >> V; // 计算d的三次方根表达式double d = pow(D * D * D - (6 * V) / pi, 1.0 / 3);// 保留3位小数输出cout << fixed << setprecision(3) << d << endl;return 0;
}