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

【题目链接】

链接

【题解】

原题求的是球面面积

可以理解为首先求多面体重心,然后算球面多边形的面积

求重心需要将多面体进行四面体剖分,从而计算出每一个四面体的重心和体积,加权平均即为整个多面体的重心

四面体体积可以用一个点引出的三条向量的积乘 \(\frac 1 6\)

四面体重心坐标是四个顶点坐标平均数

根据题目提示,球面多边形面积为三个二面角之和减去 \(\pi\),那么我们需要求二面角

先求出法向量,然后点积求向量二面角

【代码】

// Copyright lzt
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long, long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i, j, k) for (register int i = (int)(j); i <= (int)(k); i++)
#define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
#define Debug(...) fprintf(stderr, __VA_ARGS__) inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
x = 10 * x + ch - '0';
ch = getchar();
}
return x * f;
}
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 1000005
#define mo 999999137
typedef long long int64;
typedef double db;
template <class T>
void read(T &res) {
res = 0;
T f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template <class T>
void out(T x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x >= 10)
out(x / 10);
putchar('0' + x % 10);
}
const db PI = acos(-1.0);
struct Point {
db x, y, z;
Point() {}
Point(db _x, db _y, db _z) {
x = _x;
y = _y;
z = _z;
}
friend Point operator+(const Point &a, const Point &b) { return Point(a.x + b.x, a.y + b.y, a.z + b.z); }
friend Point operator-(const Point &a, const Point &b) { return Point(a.x - b.x, a.y - b.y, a.z - b.z); }
friend Point operator*(const Point &a, const db &d) { return Point(a.x * d, a.y * d, a.z * d); }
friend Point operator/(const Point &a, const db &d) { return Point(a.x / d, a.y / d, a.z / d); }
friend Point operator*(const Point &a, const Point &b) {
return Point(a.y * b.z - a.z * b.y, -a.x * b.z + a.z * b.x, a.x * b.y - a.y * b.x);
}
friend db dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
Point operator-=(const Point &b) { return *this = *this - b; }
Point operator+=(const Point &b) { return *this = *this + b; }
Point operator/=(const db &d) { return *this = *this / d; }
Point operator*=(const db &d) { return *this = *this * d; }
db norm() { return sqrt(x * x + y * y + z * z); }
} P[55], G;
vector<Point> S[85];
int N, F;
Point GetG(Point p, Point a, Point b, Point c) { return (p + a + b + c) / 4.0; }
db GetV(Point p, Point a, Point b, Point c) {
a -= p;
b -= p;
c -= p;
db res = abs(dot(a, b * c));
res /= 6.0;
return res;
}
Point CalcG() {
Point t = Point(0.0, 0.0, 0.0);
db sv = 0.0;
for (int i = 1; i <= F; ++i) {
int s = S[i].size();
for (int j = 0; j <= s - 1; ++j) {
Point tmp = GetG(P[1], S[i][j], S[i][(j + 1) % s], S[i][(j + 2) % s]);
db v = GetV(P[1], S[i][j], S[i][(j + 1) % s], S[i][(j + 2) % s]);
sv += v;
t += tmp * v;
}
}
t /= sv;
return t;
}
db CalcTangle(Point p, Point x, Point y, Point z) {
x -= p;
y -= p;
z -= p;
return acos(dot(x * y, x * z) / (x * y).norm() / (x * z).norm());
}
void Init() {
read(N);
read(F);
db x, y, z;
for (int i = 1; i <= N; ++i) {
scanf("%lf%lf%lf", &x, &y, &z);
P[i] = Point(x, y, z);
}
int k, a;
for (int i = 1; i <= F; ++i) {
read(k);
for (int j = 1; j <= k; ++j) {
read(a);
S[i].pb(P[a]);
}
}
}
void Solve() {
Point G = CalcG();
for (int i = 1; i <= F; ++i) {
int s = S[i].size();
db x = -(s - 2) * PI;
for (int j = 0; j < s; ++j) {
x += CalcTangle(G, S[i][j], S[i][(j + 1) % s], S[i][(j - 1 + s) % s]);
}
printf("%.7lf\n", x / (4 * PI));
}
}
int main() {
Init();
Solve();
return 0;
}

[LOJ 2070] 「SDOI2016」平凡的骰子的更多相关文章

  1. LOJ#2070. 「SDOI2016」平凡的骰子(计算几何)

    题面 传送门 做一道题学一堆东西不管什么时候都是美好的体验呢-- 前置芝士 混合积 对于三个三维向量\(a,b,c\),定义它们的混合积为\((a\times b)\cdot c\),其中$\time ...

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

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

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

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

  4. Loj #3096. 「SNOI2019」数论

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

  5. Loj #3093. 「BJOI2019」光线

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

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

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

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

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

  8. Loj #3059. 「HNOI2019」序列

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

  9. Loj #3056. 「HNOI2019」多边形

    Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...

随机推荐

  1. 鸟哥的linux私房菜 - 第5/6/7/9章(在线求助 man page、Linux档案权限与目录配置、Linux档案与目录管理、压缩与打包)

    第五章.在线求助 man page X window与文本模式的切换 Ctrl+Alt+F1~F6:文字接口登入tty1~tty6终端机: Ctrl+Alt+F7:图形接口桌面. 注销当前用户:exi ...

  2. 查 101.201.62.30 IP信誉方法

    查 101.201.62.30 IP信誉方法https://www.virustotal.com/#/ip-address/101.201.62.30https://talosintelligence ...

  3. lxml解析html与元素定位

    lxml.beautifulsoup和正则表达式都可以解析定位html元素.前两者中,lxml比beautifulsoup效率高,所以采用lxml解析html. 方法: from lxml impor ...

  4. Xshell 主机和远程机之间的文件传输

    (1)宿主机传输文件到远程机 方法1:直接拖动文件至xshell远程机命令行界面 方法2:远程机命令行输入rz打开文件选择框 (2)远程机传输文件到宿主机 远程机命令行界面上输入sz xxx.txt( ...

  5. 为BindingList添加Sort

    最近在优化WPF性能时, 发现在特定条件下BindingList比ObservableCollection性能更高, 因为它提供Disable/Enable 更改通知的方法.这样我们可以不需要很频繁的 ...

  6. shell ss命令

    ss命令用来显示处于活动状态的套接字信息.ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容.但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比net ...

  7. java 发邮件 代码

    /** * java发送带附件的邮件 * 周枫 * 2013.8.10 */ package com.dsideal.Util; import javax.mail.*; import javax.m ...

  8. 创建oracle数据库图示(一步一步教你安装oracle)

    123456 密码 版权声明:本文为博主原创文章,未经博主允许不得转载.

  9. 使用Postman测试请求

    Postman是什么 在开发或者调试网络程序或者是网页B/S模式的程序的时候,需要一些方法来跟踪网页请求,用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具. 网页调试工具Postm ...

  10. NSMutableAttributedString及NSMutableParagraphStyle的使用

    一.在iOS开发中,常常会有一段文字显示不同的颜色和字体,或者给某几个文字加删除线或下划线的需求.之前在网上找了一些资料,有的是重绘UILabel的textLayer,有的是用html5实现的,都比较 ...