Intersection of Two Prisms(AOJ 1313)
- 原题如下:
Suppose that P1 is an infinite-height prism whose axis is parallel to the z-axis, and P2 is also an infinite-height prism whose axis is parallel to the y-axis. P1 is defined by the polygon C1 which is the cross section of P1 and the xy-plane, and P2is also defined by the polygon C2 which is the cross section of P2 and the xz-plane.
Figure I.1 shows two cross sections which appear as the first dataset in the sample input, and Figure I.2 shows the relationship between the prisms and their cross sections.
Figure I.1: Cross sections of Prisms
Figure I.2: Prisms and their cross sections
Figure I.3: Intersection of two prisms
Figure I.3 shows the intersection of two prisms in Figure I.2, namely, P1 and P2.
Write a program which calculates the volume of the intersection of two prisms.
Input
The input is a sequence of datasets. The number of datasets is less than 200.
Each dataset is formatted as follows.
m n
x11 y11
x12 y12
.
.
.
x1m y1m
x21 z21
x22 z22
.
.
.
x2n z2nm and n are integers (3 ≤ m ≤ 100, 3 ≤ n ≤ 100) which represent the numbers of the vertices of the polygons, C1 and C2, respectively.
x1i, y 1 i, x 2j and z 2j are integers between -100 and 100, inclusive. ( x 1i, y 1i) and ( x 2j , z 2j) mean the i-th and j-th vertices' positions of C 1 and C 2respectively.
The sequences of these vertex positions are given in the counterclockwise order either on the xy-plane or the xz-plane as in Figure I.1.
You may assume that all the polygons are convex, that is, all the interior angles of the polygons are less than 180 degrees. You may also assume that all the polygons are simple, that is, each polygon's boundary does not cross nor touch itself.
The end of the input is indicated by a line containing two zeros.
Output
For each dataset, output the volume of the intersection of the two prisms, P1 and P2, with a decimal representation in a line.
None of the output values may have an error greater than 0.001. The output should not contain any other extra characters.
Sample Input
4 3
7 2
3 3
0 2
3 1
4 2
0 1
8 1
4 4
30 2
30 12
2 12
2 2
15 2
30 8
13 14
2 8
8 5
13 5
21 7
21 9
18 15
11 15
6 10
6 8
8 5
10 12
5 9
15 6
20 10
18 12
3 3
5 5
10 3
10 10
20 8
10 15
10 8
4 4
-98 99
-99 -99
99 -98
99 97
-99 99
-98 -98
99 -99
96 99
0 0Output for the Sample Input
4.708333333333333
1680.0000000000005
491.1500000000007
0.0
7600258.4847715655 - 题解:朴素想法,求出公共部分的凸多面体的顶点坐标,然后再计算其体积。公共部分的凸多面体的顶点都是一个棱柱的侧面与另一个棱柱的侧棱的交点,可以通过O(nm)时间的枚举求得,但因为涉及三维空间的几何运算,实现起来是非常麻烦的。
事实上,沿x轴对棱柱切片即可:按某个值对侧棱与z轴平行的棱柱P1切片后,就得到了[y1,y2]*(-∞,∞)这样的在z轴方向无限延伸的长方形的横截面,同样的,我们按某个x值对侧棱与y轴平行的棱柱P2切片后,就得到了(-∞,∞)*[z1,z2]这样的在y轴方向无限延伸的长方形的横截面。因此,我们按某个x值对两个棱柱的公共部分切片后,得到的横截面就是长方形[y1,y2]*[z1,z2]。而长方形的面积通过(y2-y1)*(z2-z1)就可以求得,关于x轴对面积求积分就能得到公共部分的体积了。
首先,枚举出原棱柱底面顶点的所有x坐标并排序,在相邻两个x坐标之间的区间中按x值切片得到的长方形的顶点坐标是关于x的线性函数,所以面积就是关于x的二次函数,其积分很容易计算,虽然可以通过求得表达式后再来计算二次函数的积分,但应用Simpson公式则更为轻松。Simpson公式如下:
Simpson公式就是在数值积分中用二次函数来近似原函数进行积分而得到的公式,如果原函数本身就是次数不超过二的多项式,那么用Simpson公式就可以得到精确的积分值。利用该公式,无需求出关于x的多项式,而只要计算按区间的端点和中点切片得到的长方形的面积就够了。
- 代码:
#include<cstdio>
#include<algorithm>
#include<vector> using namespace std; const int INF=0x3f3f3f3f;
const double EPS=1e-;
const int MAX_N=;
int N,M;
int X1[MAX_N], Y1[MAX_N], X2[MAX_N], Z2[MAX_N]; double max(double x, double y)
{
if (x>y+EPS) return x;
return y;
} double min(double x, double y)
{
if (x<y-EPS) return x;
return y;
} double width(int * X, int * Y, int n, double x)
{
double lb=INF, ub=-INF;
for (int i=; i<n; i++)
{
double x1=X[i], y1=Y[i], x2=X[(i+)%n], y2=Y[(i+)%n];
if ((x1-x)*(x2-x)<= && x1!=x2)
{
double y=y1+(y2-y1)*(x-x1)/(x2-x1);
lb=min(lb, y);
ub=max(ub, y);
}
}
return max(0.0, ub-lb);
} int main()
{
while (~scanf("%d %d", &M, &N))
{
if (M== && N==) break;
for (int i=; i<M; i++)
{
scanf("%d %d", &X1[i], &Y1[i]);
}
for (int i=; i<N; i++)
{
scanf("%d %d", &X2[i], &Z2[i]);
}
int min1=*min_element(X1, X1+M), max1=*max_element(X1, X1+M);
int min2=*min_element(X2, X2+N), max2=*max_element(X2, X2+N);
vector<int> xs;
for (int i=; i<M; i++) xs.push_back(X1[i]);
for (int i=; i<N; i++) xs.push_back(X2[i]);
sort(xs.begin(), xs.end());
double res=;
for (int i=; i+<xs.size(); i++)
{
double a=xs[i], b=xs[i+], c=(a+b)/;
if (min1<=c && c<=max1 && min2<=c && c<=max2)
{
double fa=width(X1, Y1, M, a)*width(X2, Z2, N, a);
double fb=width(X1, Y1, M, b)*width(X2, Z2, N, b);
double fc=width(X1, Y1, M, c)*width(X2, Z2, N, c);
res+=(b-a)/*(fa+*fc+fb);
}
}
printf("%.10f\n", res);
}
}
Intersection of Two Prisms(AOJ 1313)的更多相关文章
- UVALive 5075 Intersection of Two Prisms(柱体体积交)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- [LeetCode] Intersection of Two Arrays II 两个数组相交之二
Given two arrays, write a function to compute their intersection. Example:Given nums1 = [1, 2, 2, 1] ...
- [LeetCode] Intersection of Two Arrays 两个数组相交
Given two arrays, write a function to compute their intersection. Example:Given nums1 = [1, 2, 2, 1] ...
- [LeetCode] Intersection of Two Linked Lists 求两个链表的交点
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- 【leetcode】Intersection of Two Linked Lists
题目简述: Write a program to find the node at which the intersection of two singly linked lists begins. ...
- AOJ 0121: Seven Puzzle【BFS】
From: AOJ 0121 思路:与前几题的bfs不同,这次的bfs没有明确的移动对象,看似任意一个数都可以当成对象移动.这时我们只需要抓住一个格子就行,比如我们把0作为移动对象,那么0在地图中漫游 ...
- [LintCode] Intersection of Two Linked Lists 求两个链表的交点
Write a program to find the node at which the intersection of two singly linked lists begins. Notice ...
- LeetCode Intersection of Two Arrays
原题链接在这里:https://leetcode.com/problems/intersection-of-two-arrays/ 题目: Given two arrays, write a func ...
- AOJ DSL_2_C Range Search (kD Tree)
Range Search (kD Tree) The range search problem consists of a set of attributed records S to determi ...
随机推荐
- Azure认知服务之表格识别器
认知服务 Azure 认知服务的目标是帮助开发人员创建可以看.听.说.理解甚至开始推理的应用程序. Azure 认知服务中的服务目录可分为五大主要支柱类别:视觉.语音.语言.Web 搜索和决策.开发人 ...
- Memcached高可用组件之repcached
在前边的tomcat session server msm的那篇博客我们用memcached做tomcat session服务器,默认官方memcached是不支持主从同步的,为了解决memcache ...
- mosquitto基于SSL/TLS安全认证测试MQTT
一.环境搭建 1.mosquitto介绍 mosquitto是一个实现了MQTT3.1协议的代理服务器,由MQTT协议创始人之一的Andy Stanford-Clark开发,它为我们提供了非常棒的轻量 ...
- vue自定义可输入的选择框组件
vue自定义可输入的选择框组件 props: 属性 说明 类型 默认值 selectDataList 下拉框中的内容 Array 空数组([]) value 输入框中的内容 String 空字符串(& ...
- 通过C#实现OPC-UA服务端(二)
前言 通过我前面的一篇文件,我们已经能够搭建一个OPC-UA服务端了,并且也拥有了一些基础功能.这一次咱们就来了解一下OPC-UA的服务注册与发现,如果对服务注册与发现这个概念不理解的朋友,可以先百度 ...
- python numpy常用的数学和统计函数
numpy模块的核心就是基于数组的运算,相比于列表和其他数据结构,数组的运算效率是最高的.在统计分析和挖掘过程中,经常会使用到numpy模块的函数,以下是常用的数学函数和统计函数: 常数p就是圆周率 ...
- latex:矩阵环境
矩阵的最大列数值是在MaxMatrixCols计数器中设定的,默认值是10.可使用计数器设置命令修改其值,例如需要用到15列:\setcounter{MaxMatrixCols}{15};当超宽矩阵排 ...
- django学习(一)
1.django版本的选择问题 在学习django之前,我们先做一个基本问题的讨论,这个问题是关于django版本的问题.我们进入官网,可以查看django版本的情况. 关于django的版本的问题, ...
- Java面试题(Spring Boot/Spring Cloud篇)
Spring Boot/Spring Cloud 104.什么是 spring boot? SpringBoot是一个框架,一种全新的编程规范,他的产生简化了框架的使用,所谓简化是指简化了Spring ...
- 借助FRP反向代理实现内网穿透
一.frp 是什么? frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP.UDP.HTTP.HTTPS 等多种协议.可以将内网服务以安全.便捷的方式通过具有公网 IP 节点的中转暴露到公 ...