zoj 2369 Two Cylinders

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2369

题意:已知两个无限长的圆柱的半径,它们轴线相交且垂直,求相交部分的体积。

思路:以相交点为坐标原点,建立三维坐标系,列出 两个圆柱的公式,把三维转化为一维积分公式

    V1 : x2 + y2 = r12    ==>  y = sqrt ( r12 - x2  );

    V2 : x2 + z2 = r22    ==>  z = sqrt ( r22 - x2  );

    V = ∫∫∫ dv = ∫∫∫ dxdydz = ∫(∫∫ dydz)dx    积分区间:( 0 <= x <= r1 ,  0 <= x <= r2  )

    所以: V = ∫0min(r1, r2) sqrt(( r12-x2) * (r22-x2));

计算这个积分,我用了好几种方法,但是只有 变步长simpon 积分达到精度要求,我也不清楚什么原因。下面是几种求积分的算法:

测试数据:

10
1 1
2 1
3 2
5 2
8 3
8 4
99 2
99 56
84 31
91 17

正确答案:

5.3333
12.1603
70.9361
123.0975
444.2909
778.2605
2488.0144
1869197.4256
498415.2860
164517.4621

变步长 simpon 积分:(得到正确结果)

 #include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <math.h>
using namespace std; const double eps = 1e-;
double r1, r2; double f(double x)
{
return . * sqrt((r1*r1 - x*x) * (r2*r2 - x*x));
} double simpson(double a, double b)
{
int n, k;
double h, t1, t2, s1, s2, ep, p, x;
n = , h = b - a; t1 = h * ( f(a) + f(b) ) / .; //计算T1 = (b-a)/2*[f(a) + f(b)]
s1 = t1; //T1代替S1
ep = eps + .;
while(ep >= eps)
{
p = ;
for(k = ; k <= n-; k++)
{
x = a + (k + 0.5) * h;
p += f(x);
}
t2 = (t1 + h * p) / .; //计算T2n = Tn/2 + h/2 * [(累加)f(xk + 0.5)];
s2 = (. * t2 - t1) / .; //计算Sn = (4*Tn - Tn) / 3;
ep = fabs(s2 - s1); //计算精度
t1 = t2, s1 = s2, n += n, h /= .;
}
return s2;
} int main()
{
int CASE;
freopen("zoj2369.txt", "r", stdin);
cin >> CASE;
while(CASE--)
{
scanf("%lf%lf", &r1, &r2);
if(r2 < r1) swap(r1, r2);
double t = simpson(., r1);
printf("%.4lf\n", t); }
return ;
} /* 结果:
5.3333
12.1603
70.9361
123.0974
444.2908
778.2604
2488.0144
1869197.4256
498415.2860
164517.4621
*/

勒让德-高斯求积(精度不够):

 #include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <math.h>
using namespace std; const double eps = 1e-;
double r1, r2; double f(double x)
{
return . * sqrt((r1*r1 - x*x) * (r2*r2 - x*x));
} double lrgs(double a, double b)
{
int m, i, j;
double s, p, ep, aa, bb, w, x, g, h;
static double t[] = {-0.9061798459, -0.5384693101, 0.0, 0.5384693101, 0.9061798459};
static double c[] = {0.2369268851, 0.4786286705, 0.5688888889, 0.4786286705, 0.2369268851};
m = ;
h = b - a; s = fabs(0.001 * h);
p = 1.0e+35, ep = eps + 1.0;
while(ep >= eps && fabs(h) > s)
{
g = .;
for(i = ; i <= m; i++)
{
aa = a + (i-.) * h, bb = a + i * h;
w = .;
for(j = ; j < ; j++)
{
x = ((bb - aa) * t[j] + (bb + aa)) / .;
w += f(x) * c[j];
}
g += w;
}
g = g * h / .;
ep = fabs(g-p) / (. + fabs(g));
p = g, m += , h = (b-a) / m;
}
return g;
} int main()
{
int t;
freopen("zoj2369.txt", "r", stdin);
scanf("%d", &t);
while(t--)
{
scanf("%lf%lf", &r1, &r2);
if(r1 > r2) swap(r1, r2);
printf("%.4lf\n", lrgs(, r1));
}
return ;
} /*结果
5.3333
12.1619
70.9440
123.1138
444.3504
778.3592
2488.3679
1869425.2091
498482.1853
164540.5195
*/

龙贝格求积法(精度不够):

 #include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <cstring>
#include <math.h>
using namespace std; const double eps = 1e-;
double r1, r2; double f(double x)
{
return . * sqrt((r1*r1 - x*x) * (r2*r2 - x*x));
} double romb(double a, double b)
{
int n, m, i, k;
double y[], h, ep, p, x, s, q;
h = b - a;
y[] = h * ((f(a) + f(b))) / .;
m = , n = , ep = eps + 1.0;
while(ep >= eps )
{
p = 0.0;
for(i = ; i < n; i++)
{
x = a + (i+0.5) * h;
p += f(x);
}
p = (y[] + h * p) /.;
s = 1.0;
for(k = ; k <= m; k++)
{
s = . * s;
q = (s*p - y[k-]) / (s - .);
y[k - ] = p, p = q;
}
ep = fabs(q - y[m-]);
m = m + , y[m - ] = q, n += n, h /= .;
}
return q;
} int main()
{
int t;
freopen("zoj2369.txt", "r", stdin);
freopen("zzin1.txt", "w", stdout);
scanf("%d", &t);
while(t--)
{
scanf("%lf%lf", &r1, &r2);
if(r1 > r2) swap(r1, r2);
printf("%.4lf\n", romb(, r1));
}
return ;
} /*结果
5.3333
12.1529
70.8978
123.0697
444.1897
778.0925
2487.8023
1869191.3654
498410.2627
164515.7323
*/

也不知最后两个代码那里写搓了,真心无力。

下面给出标程:

 #include <cmath>
#include <cstdio>
#include <algorithm> using namespace std; const long double H = 5e-; struct F {
long double rr1, rr2;
F(long double r1, long double r2) : rr1(r1 * r1), rr2(r2 * r2) {
}
long double operator()(long double x) const {
x = x * x;
return sqrt((rr2 - x) * (rr1 - x));
}
}; int main() {
int re; scanf("%d", &re);
for (int ri = ; ri <= re; ++ri) {
long double r1, r2;
scanf("%Lf%Lf", &r1, &r2);
if (r1 > r2) {
swap(r1, r2);
}
int n = int(r1 / H);
// int n = 1000000;
long double h = r1 / n / ;
F f(r1, r2);
long double s = ;
s += f() + f(r1);
for (int i = ; i < * n; ++i) {
if (i & ) {
s += * f(i * h);
} else {
s += * f(i * h);
}
}
s /= * n;
s *= * r1;
printf("%.6Lf\n", s);
} return ;
}

网上看的大牛的代码,0ms秒过,我的用了290ms, 标程用了310ms

 #include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std; #define db double
#define rt return
#define cs const cs db eps = 1e-;
inline int sig(db x){rt (x>eps)-(x<-eps);} db r1, r2; inline db f(db x) {
rt . * sqrt(r1*r1-x*x) * sqrt(r2*r2-x*x);
} inline db simpson(db a, db b) {
rt (b-a)*(f(a) + .*f((a+b)/.) + f(b)) / .;
} inline db calc(db a, db b, int depth) {
db total = simpson(a, b), mid = (a+b) / .;
db tmp = simpson(a, mid) + simpson(mid, b);
if(sig(total-tmp) == && depth > ) rt total;
rt calc(a, mid, depth + ) + calc(mid, b, depth + );
} int main() {
// freopen("std.in", "r", stdin);
int T;
freopen("zoj2369.txt", "r", stdin);
scanf("%d", &T);
while(T--) {
scanf("%lf%lf", &r1, &r2);
if(sig(r1-r2) > ) swap(r1, r2);
printf("%.4lf\n", . * calc(., r1, ));
}
rt ; }

zoj 2369 Two Cylinders的更多相关文章

  1. POJ 2296 Map Labeler / ZOJ 2493 Map Labeler / HIT 2369 Map Labeler / UVAlive 2973 Map Labeler(2-sat 二分)

    POJ 2296 Map Labeler / ZOJ 2493 Map Labeler / HIT 2369 Map Labeler / UVAlive 2973 Map Labeler(2-sat ...

  2. ZOJ题目分类

    ZOJ题目分类初学者题: 1001 1037 1048 1049 1051 1067 1115 1151 1201 1205 1216 1240 1241 1242 1251 1292 1331 13 ...

  3. ZOJ People Counting

    第十三届浙江省大学生程序设计竞赛 I 题, 一道模拟题. ZOJ  3944http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=394 ...

  4. ZOJ 3686 A Simple Tree Problem

    A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a rooted tree, each no ...

  5. ZOJ Problem Set - 1394 Polar Explorer

    这道题目还是简单的,但是自己WA了好几次,总结下: 1.对输入的总结,加上上次ZOJ Problem Set - 1334 Basically Speaking ac代码及总结这道题目的总结 题目要求 ...

  6. ZOJ Problem Set - 1392 The Hardest Problem Ever

    放了一个长长的暑假,可能是这辈子最后一个这么长的暑假了吧,呵呵...今天来实验室了,先找了zoj上面简单的题目练练手直接贴代码了,不解释,就是一道简单的密文转换问题: #include <std ...

  7. ZOJ Problem Set - 1049 I Think I Need a Houseboat

    这道题目说白了是一道平面几何的数学问题,重在理解题目的意思: 题目说,弗雷德想买地盖房养老,但是土地每年会被密西西比河淹掉一部分,而且经调查是以半圆形的方式淹没的,每年淹没50平方英里,以初始水岸线为 ...

  8. ZOJ Problem Set - 1006 Do the Untwist

    今天在ZOJ上做了道很简单的题目是关于加密解密问题的,此题的关键点就在于求余的逆运算: 比如假设都是正整数 A=(B-C)%D 则 B - C = D*n + A 其中 A < D 移项 B = ...

  9. ZOJ Problem Set - 1001 A + B Problem

    ZOJ ACM题集,编译环境VC6.0 #include <stdio.h> int main() { int a,b; while(scanf("%d%d",& ...

随机推荐

  1. 2018科大讯飞AI营销算法大赛全面来袭,等你来战!

    AI技术已成为推动营销迭代的重要驱动力.AI营销高速发展的同时,积累了海量的广告数据和用户数据.如何有效应用这些数据,是大数据技术落地营销领域的关键,也是检测智能营销平台竞争力的标准. 讯飞AI营销云 ...

  2. 【转载】Android 内存溢出如何发生的。

    [转载]Android 内存溢出如何发生的. 且谈Android内存溢出 前言 关于android的内存溢出在创新文档库中也有不少,网络上也有很多这方面的资料.所以这遍文章不算是正真意义上的创新,仅仅 ...

  3. window.open()与window.showModalDialog区别

    window.open()与window.showModalDialog区别 弹出窗口两种方式:    1.window.showModalDialog:      var feature = &qu ...

  4. 面试中要注意的 3 个 JavaScript 问题

    JavaScript 是 所有现代浏览器 的官方语言.因此,各种语言的开发者面试中都会遇到 JavaScript 问题. 本文不讲最新的 JavaScript 库,通用开发实践,或任何新的 ES6 函 ...

  5. 软件工程 作业part1

    自我介绍 老师您好,我叫宋雨,本科在长春理工大学,专业是计算机科学与技术. 1.回想一下你曾经对计算机专业的畅想:当初你是如何做出选择计算机专业的决定?你认为过去接触的课程是否符合你对计算机专业的期待 ...

  6. 第十九次ScrumMeeting会议

    第十九次Scrum Meeting 时间:2017/12/9 地点:三公寓大厅 人员:蔡帜 王子铭 游心 解小锐 王辰昱 李金奇 杨森 陈鑫 赵晓宇 照片: 目前工作进展 名字 今日 明天的工作 蔡帜 ...

  7. .net改善程序性能建议

    对改善程序性能的建议. 文章:https://msdn.microsoft.com/zh-cn/library/ms973838.aspx

  8. scrapy(2)——scrapy爬取新浪微博(单机版)

    Sina爬虫教程   Scrapy环境搭建   环境:window10 + python2.7(包含scrapy)+ mongoDB 1.1 安装集成了python2.7的anaconda   ana ...

  9. iOS- <项目笔记>项目配置常见文件

    项目常见文件 1.main.m * 里面有一个程序的入口:main函数 2.Prefix.pch文件 * pch文件中的内容能被项目中的其他任何文件共享\包含\访问 * 如果定义的内容只用在OC环境中 ...

  10. 【Linux】- apt-get命令

    apt-get,是一条linux命令,适用于deb包管理式的操作系统,主要用于自动从互联网的软件仓库中搜索.安装.升级.卸载软件或操作系统. Advanced Package Tool,又名apt-g ...