题面

传送门

做一道题学一堆东西不管什么时候都是美好的体验呢……

前置芝士

混合积

对于三个三维向量\(a,b,c\),定义它们的混合积为\((a\times b)\cdot c\),其中$\times \(表示叉乘,\)\cdot\(表示点乘,记为\)[a\ b\ c]$

关于它的几何意义的话……图片来自网络

其中\(Prj_{a\times b}c\)代表的是\(c\)这个向量在\(a\times b\)这个向量上的投影

那么显然我们最后得到的是以这三个向量为三条临边的一个六面体的体积

四面体体积

假设四面体的四个顶点分别为\(A,B,C,D\),并设三个向量\(a=B-A,b=C-A,c=D-A\),那么这个正四面体的体积就是\({1\over 6}[a\ b\ c]\)

这个应该比较显然吧……看上面那幅图,四面体的体积是以\(ab\)这个平行四边形为底,\(c\)为顶点的棱锥的一半,而棱锥的体积是棱柱的\({1\over 3}\),所以四面体体积就是六面体的\({1\over 6}\)了

凸多面体的重心

我们先来考虑一下凸多边形的重心好了……

对于三角形,它的重心就是它所有坐标的平均值

那么对于凸多边形,我们把它三角剖分了,记第\(i\)块的重心为\(a_i\),面积为\(m_i\),那么凸多边形的重心就是

\[{\sum_{i=1}^na_i\times m_i\over \sum_{i=1}^nm_i}
\]

那么凸多面体也差不多了,我们把它给四面体剖分了,然后也差不多按上面的算就好了

关于四面体剖分,具体的说我们在多面体中随便选一个点,比方说是\(p_1\),然后把每一个面给三角剖分,那么三角形就和选定的点构成了一个四面体。设\(v_i\)表示第\(i\)个四面体的体积,\(a_i\)表示重心,则最终多面体的重心为

\[{\sum_{i=1}^na_i\times v_i\over \sum_{i=1}^nv_i}
\]

二面角

这玩意儿班里数学课正在上然而我正在停课

简单来说就是两个平面的夹角

我们假设现在有\(a,b,c\)三个向量,要求\(ab\)这个平面和\(ac\)这个平面的二面角

那么求出\(ab\)和\(ac\)的法向量(法向量可以直接用叉积算),两个法向量之间的夹角就是二面角了,法向量之间的夹角直接用点积除以长度计算

可以画个图来理解。我们俯视的话,即要求二面角\(\angle 1\),那么显然两个法向量的夹角\(\angle 2=\angle 1\)

题解

总结起来的话……

三维计算几何。

需要混合积求四面体体积;

四面体剖分后合并带权重心求总重心;

四面体重心的横纵坐标是四个顶点的横纵坐标的平均数;

三维差积求平面的法向量;

点积求法向量夹角(二面角)

这些知识就可以了AC此题了。

时间复杂度\(O(nf)\)

顺便说一下数据范围是\(n,f\leq 100\),题面里错了

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int N=105;const double Pi=acos(-1.0);
struct node{
double x,y,z;
inline node(){}
inline node(R double xx,R double yy,R double zz):x(xx),y(yy),z(zz){}
inline node operator +(const node &b)const{return node(x+b.x,y+b.y,z+b.z);}
inline node operator -(const node &b)const{return node(x-b.x,y-b.y,z-b.z);}
inline node operator *(const node &b)const{return node(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);}
inline double operator ^(const node &b)const{return x*b.x+y*b.y+z*b.z;}
inline node operator *(const double &b)const{return node(x*b,y*b,z*b);}
inline node operator /(const double &b)const{return node(x/b,y/b,z/b);}
inline double norm(){return sqrt(x*x+y*y+z*z);}
}p[N],h[N*N],u,v;
int f[N][N],c[N];double sum,tmp;
int n,m;
inline double cross(const node &a,const node &b,const node &c){
node p=b*a,q=c*a;return acos((p^q)/p.norm()/q.norm());
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d%d",&n,&m);
fp(i,1,n)scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
fp(i,1,m){
scanf("%d",&c[i]);
fp(j,1,c[i])scanf("%d",&f[i][j]);
}
u=p[1],v=node(0,0,0),sum=0;
fp(i,1,m){
node u2=p[f[i][1]],v1,v2,t;
fp(j,2,c[i]-1){
v1=p[f[i][j]],v2=p[f[i][j+1]];
t=(u+u2+v1+v2)*0.25,tmp=fabs(((v1-u2)*(v2-u2))^(u-u2));
v=v+t*tmp,sum+=tmp;
}
}
tmp=1.0/sum,u=v*tmp,tmp=0.25/Pi;
fp(i,1,n)p[i]=p[i]-u;
fp(i,1,m){
sum=0;
fp(j,2,c[i]-1)sum+=cross(p[f[i][j]],p[f[i][j-1]],p[f[i][j+1]]);
sum+=cross(p[f[i][1]],p[f[i][c[i]]],p[f[i][2]]),
sum+=cross(p[f[i][c[i]]],p[f[i][c[i]-1]],p[f[i][1]]);
sum-=(c[i]-2)*Pi;
printf("%.7lf\n",sum*tmp);
}
return 0;
}

LOJ#2070. 「SDOI2016」平凡的骰子(计算几何)的更多相关文章

  1. [LOJ 2070] 「SDOI2016」平凡的骰子

    [LOJ 2070] 「SDOI2016」平凡的骰子 [题目链接] 链接 [题解] 原题求的是球面面积 可以理解为首先求多面体重心,然后算球面多边形的面积 求重心需要将多面体进行四面体剖分,从而计算出 ...

  2. 【LOJ】#2070. 「SDOI2016」平凡的骰子

    题解 用了一堆迷之复杂的结论结果迷之好写的计算几何???? 好吧,要写立体几何了 如果有名词不懂自己搜吧 首先我们求重心,我们可以求带权重心,也就是x坐标的话是所有分割的小四面体的x坐标 * 四面体体 ...

  3. LOJ#2082. 「JSOI2016」炸弹攻击 2(计算几何+双指针)

    题面 传送门 题解 我们枚举一下发射源,并把敌人和激光塔按极角排序,那么一组合法解就是两个极角之差不超过\(\pi\)且中间有敌人的三元组数,预处理一下前缀和然后用双指针就行了 //minamoto ...

  4. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  5. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  6. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  7. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

  8. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

  9. Loj #3059. 「HNOI2019」序列

    Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...

随机推荐

  1. Eclipse 安装Hibernate Tools 工具 提高开发效率

    1.打开Eclipse 开发工具  2.配置使用hibernate Tools 3.选择search 选项卡,搜索 hibernate 关键字 点击Install       Next  finish ...

  2. 迷你MVVM框架 avalonjs 学习教程4、数据填充

    MVVM是前端的究极解决方案,你们可能用过jQuery,但那个写的代码不易维护:你们可以听过说requirejs与seajs,传说中的模块开发,加载器,但它们的最终目标是打包:你们可能听过unders ...

  3. UIview需要知道的一些事情:setNeedsDisplay、setNeedsLayout

    UIview需要知道的一些事情:setNeedsDisplay.setNeedsLayout 1.在Mac OS中NSWindow的父类是NSResponder,而在i OS 中UIWindow 的父 ...

  4. sql的预编译问题

  5. codeforces:Prefix Sums分析和实现

    题目大意: 给出一个函数P,P接受一个数组A作为参数,并返回一个新的数组B,且B.length = A.length + 1,B[i] = SUM(A[0], ..., A[i]).有一个无穷数组序列 ...

  6. 05-了解activiti目录结构

    数据库底层支持的23张表的增删改查 如果你不会用activiti的API,可以看一下开发文档 流程引擎ProcessEngines,最重要是这个玩意. libs就更重要了,我们使用一个框架主要是使用它 ...

  7. java文档打包成压缩包并且下载

    需求,根据产品ID查询产品详情,产品详情会返回产品的一些文案,以及图片的url.需要做成,将文案信息记录在一个txt文档中,然后图片下载到文件夹,最后下载到本地,下载后自动删除刚才生成的文件夹以及文件 ...

  8. gnuc与ansic

    GNU c与标准c的区别 1) 零长度数组 struct var_data { int len; char data[0]; }test: int a; test.data -->a 2)cas ...

  9. Java 设计模式系列(十四)命令模式(Command)

    Java 设计模式系列(十四)命令模式(Command) 命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复 ...

  10. c#解决Nullable类型的转换 (包含DataContract的序列化和反序列化以及 该例子应用在反射属性setvalue的时候有用)

    using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Reflect ...