[Sdoi2016]平凡的骰子
描述
这是一枚平凡的骰子。它是一个均质凸多面体,表面有n个端点,有f个面,每一面是一个凸多边形,且任意两面不共面。将这枚骰子抛向空中,骰子落地的时候不会发生二次弹跳(这是一种非常理想的情况)。你希望知道最终每一面着地的概率。
每一面着地的概率可以用如下的方法计算:我们假设O为骰子的重心,并以O为球心,做半径为1的单位球面(记为S)。我们知道S的表面积即单位球的表面积,为4*pi,这里pi为圆周率。对于骰子的某一面C来说,球面S上存在一块区域T满足:当下落时若骰子所受重力方向与S的交点落在T中,则C就是最终着地的一面。那么C着地的概率为区域T的面积除以4*pi。
为了能更好地辅助计算球面上一块区域的面积,我们给出单位球面 S 上三角形的面积计算公式。考虑单位球面 S 上的三个两两相交的大圆,交点依次为A,B 和 C。则曲面三角形 ABC 的面积为 Area(ABC)=alpha+beta+gamma-pi,其中 alpha,beta 和 gamma 分别对应了三个二面角的大小。如下图所示。
我们保证:每一面着地的时候,重心的垂心都恰好在这一面内。也就是说不会出现摆不稳的情况。
格式
输入格式
第一行输入两个整数,分别表示端点总数n与表面总数f,分别从1开始编号。
之后n行,每行有三个浮点数x,y和z,给出了每一个端点的坐标。之后f行依次描述了每一块表面,首先给出不小于3的整数d,表示这一面的端点个数,之后d个整数按照逆时针方向(视角在骰子的外面)给出了每一个端点的编号。
输出格式
输出f行,第i行有一个浮点数,表示第i个面着地的概率。
本题中您的输出应该保留距离答案最近的7位小数,即在需要保留7位小数的前提之下与标准答案最接近。数据保证可以避免对小数点后第八位四舍五入后产生的精度误差。
样例1
样例输入1
8 6
1 0 0
1 1 0
1 0 1
1 1 1
0 0 0
0 1 0
0 0 1
0 1 1
4 1 2 4 3
4 2 6 8 4
4 6 5 7 8
4 5 1 3 7
4 3 4 8 7
4 1 5 6 2
样例输出1
0.1666667
0.1666667
0.1666667
0.1666667
0.1666667
0.1666667
限制
首先存在20%的数据,骰子为长方体。
其次存在20%的数据,骰子为四面体。
余下的数据中有30%的数据,每一面都是三角形。
对于100%的数据,4<=n<=100且4<=m<=100,所有坐标的绝对值都在10000以内。
来源
SDOI 2016 round2 day2
- 三维计算几何。
- 需要混合积求四面体体积;
- 四面体剖分后合并带权重心求总重心;
- 四面体重心的横纵坐标是四个顶点的横纵坐标的平均数;
- 三维差积求平面的法向量;
- 点积求法向量夹角(二面角)
- 这些知识就可以了AC此题了。
- 时间复杂度O(nf)O(nf),注意n,f≤100n,f≤100,题面描述有误。
#include<cmath>
#include<cstdio>
using namespace std;
inline void read(int &x){
register char ch=getchar();x=;
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
}
const int N=;
typedef double real;
const real pi=acos(-);
struct point{
real x,y,z;
point(){}
point(real _x,real _y,real _z):x(_x),y(_y),z(_z){}
point operator +(const point &a)const{
return point(x+a.x,y+a.y,z+a.z);
}
point operator -(const point &a)const{
return point(x-a.x,y-a.y,z-a.z);
}
point operator ^(const point &a)const{
return point(y*a.z-z*a.y,z*a.x-x*a.z,x*a.y-y*a.x);
}
real operator *(const point &a)const{
return x*a.x+y*a.y+z*a.z;
}
point operator /(const real &a)const{
return point(x/a,y/a,z/a);
}
const real len(){
return sqrt(x*x+y*y+z*z);
}
}P[N],H[N*N];
int n,m,Htot,f[N][N];
real val[N*N];
int main(){
read(n);read(m);
for(int i=;i<=n;i++) scanf("%lf%lf%lf",&P[i].x,&P[i].y,&P[i].z);
for(int i=;i<=m;i++){
read(f[i][]);
for(int j=;j<=f[i][];j++){
read(f[i][j]);
}
}
point u=P[];
for(int i=;i<=m;i++){
point u2=P[f[i][]],v1,v2;
for(int j=;j<f[i][];j++){
v1=P[f[i][j]];
v2=P[f[i][j+]];
H[++Htot]=(u+u2+v1+v2)/;//四面体重心
val[Htot]=fabs(((u2-v1)^(u2-v2))*(u-u2));//四面体体积
}
}
u=point(,,);
real valtot=;
for(int i=;i<=Htot;i++){
valtot+=val[i];
u=u+point(H[i].x*val[i],H[i].y*val[i],H[i].z*val[i]);
}
u=u/valtot;//球心坐标
for(int i=;i<=m;i++){
point u1,u2,u3;real co,ans=;
for(int j=,s1,s2;j<=f[i][];j++){//该平面拆成三角形,计算所有不同夹角
s1= j+;if(s1>f[i][]) s1=;
s2=s1+;if(s2>f[i][]) s2=;
u1=P[f[i][j]]-u;
u2=P[f[i][s1]]-u;
u3=P[f[i][s2]]-u;
u1=u1^u2;//面(u1,u2)的法向量
u3=u3^u2;//面(u2,u3)的法向量
co=u1*u3/u1.len()/u3.len();//二面角夹角
ans+=acos(co);
}
ans-=pi*(f[i][]-);
printf("%.7lf\n",ans//pi);
}
return ;
}
[Sdoi2016]平凡的骰子的更多相关文章
- [LOJ 2070] 「SDOI2016」平凡的骰子
[LOJ 2070] 「SDOI2016」平凡的骰子 [题目链接] 链接 [题解] 原题求的是球面面积 可以理解为首先求多面体重心,然后算球面多边形的面积 求重心需要将多面体进行四面体剖分,从而计算出 ...
- 【LOJ】#2070. 「SDOI2016」平凡的骰子
题解 用了一堆迷之复杂的结论结果迷之好写的计算几何???? 好吧,要写立体几何了 如果有名词不懂自己搜吧 首先我们求重心,我们可以求带权重心,也就是x坐标的话是所有分割的小四面体的x坐标 * 四面体体 ...
- LOJ#2070. 「SDOI2016」平凡的骰子(计算几何)
题面 传送门 做一道题学一堆东西不管什么时候都是美好的体验呢-- 前置芝士 混合积 对于三个三维向量\(a,b,c\),定义它们的混合积为\((a\times b)\cdot c\),其中$\time ...
- 【Vijos 1998】【SDOI 2016】平凡的骰子
https://vijos.org/p/1998 三维计算几何. 需要混合积求四面体体积: 四面体剖分后合并带权重心求总重心: 四面体重心的横纵坐标是四个顶点的横纵坐标的平均数: 三维差积求平面的法向 ...
- bzoj 4603 平凡的骰子
题目大意: 思路: 首先我们需要求出整个凸多面体的重心 可以通过把多面体剖分为四面体 求出每个四面体的重心 四面体的重心为四个点的坐标和/4 对每个四面体的重心 加上它们体积的权 加权平均数即为整个的 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- BZOJ1298[SCOI2009]骰子的学问
Description Input 第一行为两个整数n, m.第二行有n个整数,为a1,a2, -, an. Output 包含n行,每行m个1~n×m的正整数,各不相同,以空格分开.如果有多解,输出 ...
- Frida HOOK微信实现骰子作弊
由于微信摇骰子的功能在本地进行随机后在发送,所以存在可以hook掉判断骰子数的方法进行修改作弊. 1.frida实现hook java层函数1)写个用来测试的demo,当我们点击按钮的时候会弹出窗口显 ...
- BZOJ4516: [Sdoi2016]生成魔咒 后缀自动机
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #inclu ...
随机推荐
- 解决:ADODB.Stream 错误 '800a0bbc' 写入文件失败
重装更改目录为e盘后,上传文件出现问题.解决方法: 调用adodb.stream的savetofile方法时发生错误, ADODB.Stream 错误 800a0bbc 写入文件失败.(msxml3. ...
- 解决Windows2003的IE安全级别不能修改的问题
默认装完win2k3IE安全级别是不能修改的,不管怎么样修改,系统总提示说 “此域的推荐安全级别是“安全级-高”.您选择的级别较低.还是返回最高级别的.刚才弄voip,在win2k3虚拟机测试,差点气 ...
- 【WP8】为Webbrowser添加ScrollBar
在WP8中,控件WebBrowser没有提供对滚动条的支持,而在内置的IE中,却可以显示出滚动条(微软这是在坑我们吗),但如果在客户端使用Webbrowser的话,自己构造ScrollBar来显示 通 ...
- curl tutorial with examples of usage
原文:http://www.yilmazhuseyin.com/blog/dev/curl-tutorial-examples-usage/ 阮一峰的这个教程也不错:http://www.ruanyi ...
- 1. 自动化运维系列之Cobbler自动装机
preface 我们之前批量安装操作系统的时候都是采用pxe来安装,pxe也是通过网络安装操作系统的,但是PXE依赖于DHCP,HTTP/TFTP,kicstart等支持.安装流程如下所示: 对于上面 ...
- C#反射学习
http://www.cnblogs.com/landeanfen/p/4642814.html http://blog.csdn.net/lianjiangwei/article/details/4 ...
- 【matlab】命令行窗口一直不停的输出ans=1?
ans= 1 matlab里面的ans是一个系统量,当m文件中出现非赋值性的计算时,matlab会把结果自动存入ans. 如果m文件中每一个计算都是赋值的,即所计算的结果都是保存在自己设定的变量中的, ...
- easyui分页,编辑datagrid某条数据保存以后跳转到某一页
参考资料:http://caizhilin2010.iteye.com/blog/1731698 问题:商品列表页面采用easyui的datagrid展示数据,编辑某行数据保存以后,要求跳转到 用户在 ...
- 纯CSS制作的TAB选项卡
代码 这里主要使用表单的单选按钮来实现这个TAB显示和隐藏,首页tab里的内容默认隐藏,如果单选按钮为选中状态(checked)就显示内容.具体请看下面代码. 关于兼容性,因为是用CSS3来制作的,所 ...
- linux中如何对一个文件的内容进行处理,文件中每行有多个字段的值,中间用空格分隔开?
需求描述: 今天在帮同事看个需求,将操作系统上的文件进行修改名字,改为特定的名字,所以呢,就先把这些原名字及对应的新名字关系放到了一个文本中,对于这个文本执行循环. 文件格式如下: .00000005 ...