2017-03-18 HDU 5733 计算几何 codeforces 599E 状压dp(待补)

HDU 5733

题意:给出四面体的四个顶点,求出其内切球的球心坐标和半径,如果不存在内切球,输出"O O O O"。

tags:一堆公式。。可以做模板了

我们可以将平面上的四点得到由同一个点出发的三个矢量。这样就可以计算这三个矢量的混合积M,则M/6即为四面体体积V。

题目无解的情况当且仅当四点共面,即混合积为0。

求得四面体体积后,可以根据公式r = 3V/(S1+S2+S3+S4)得到内切球半径, S1~S4为四面体四个面的面积。

当前的问题转化为如何求四面体四个面的面积。

由于我们已经知道四个顶点的坐标,因此可以通过海伦公式来分别求解四个面的面积S1~S4,以此来求得r。

对于球心坐标,有公式:

x=(p1.x*s1+p2.x*s2+p3.x*s3+p4.x*s4)/(s1+s2+s3+s4);

y=(p1.y*s1+p2.y*s2+p3.y*s3+p4.y*s4)/(s1+s2+s3+s4);

z=(p1.z*s1+p2.z*s2+p3.z*s3+p4.z*s4)/(s1+s2+s3+s4);

si为pi做顶点时,对应的底面的面积。

// HDU 5733
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 200005;
const double eps=1e-8;

double s[4], sum, x, y, z, v;

struct Point {
    double x, y, z;
    Point operator - (const Point &b) const {    //向量 a 与 b 的点积
        return Point{x-b.x, y-b.y, z-b.z};
    }
    Point operator ^ (const Point &b) const {    //向量 a 与 b 的叉积
        return Point{(y*b.z-z*b.y), (z*b.x-x*b.z), (x*b.y-y*b.x)};
    }
} p[4];
int dcmp(double x) {        // x为混合积,判正负,x==0表示4点共面
    if(fabs(x)<eps) return 0;
    return x<0?-1:1;
}
double MixMul(Point a, Point b, Point c) {        //求向量a,b,c的混合积
    return a.x*b.y*c.z+a.y*b.z*c.x+a.z*b.x*c.y-a.x*b.z*c.y-a.y*b.x*c.z-a.z*b.y*c.x;
}
double dis(Point a, Point b) {            //两点距离
    return sqrt(pow(a.x-b.x, 2)+pow(a.y-b.y, 2)+pow(a.z-b.z, 2));
}
double Heron(double a, double b, double c) {    //海伦公式求三角形面积
    double p=(a+b+c)/2;
    return sqrt(p*(p-a)*(p-b)*(p-c));
}
double getsqr(Point a, Point b, Point c) {        //通过海伦公式求三个向量构成的面的面积
    return Heron(dis(a,b), dis(b,c), dis(a,c));
}

int main()
{
    while(~scanf("%lf %lf %lf", &p[0].x, &p[0].y, &p[0].z))
    {
        rep(i,1,3) scanf("%lf %lf %lf", &p[i].x, &p[i].y, &p[i].z);
        v=fabs(MixMul(p[0]-p[1], p[0]-p[2], p[0]-p[3]));
        if(dcmp(v)==0) {
            puts("O O O O");
            continue;
        }

        s[3]=getsqr(p[0], p[1], p[2]);        // 分别求出4个面的面积s[i]
        s[2]=getsqr(p[0], p[1], p[3]);
        s[1]=getsqr(p[0], p[2], p[3]);
        s[0]=getsqr(p[1], p[2], p[3]);
        sum=0;
        rep(i,0,3) s[i]=fabs(s[i]), sum+=s[i];    // sum为四个面的面积和,内切球半径 = v/2/sum
        x=y=z=0;
        rep(i,0,3) {
            x+=p[i].x*s[i];
            y+=p[i].y*s[i];
            z+=p[i].z*s[i];
        }
        x/=sum, y/=sum, z/=sum;        //内切球球心坐标公式
        printf("%.4f %.4f %.4f %.4f\n", x, y, z, v/2/sum);
    }

    return 0;
}
时间: 2024-11-10 08:22:48

2017-03-18 HDU 5733 计算几何 codeforces 599E 状压dp(待补)的相关文章

HDU 4114 Disney&#39;s FastPass (状压DP)

题意:给定 n 个区域,然后给定两个区域经过的时间,然后你有 k 个景点,然后给定个每个景点的区域和有票没票的等待时间,从哪些区域能够得到票,问你从景点1开始,最后到景点1,而且要经过看完这k个景点. 析:一个状压DP,dp[s1][s2][i] 表示已经访问了 s1 中的景点,拥有 s2 的票,当前在 i 区域,然后两种转移一种是去下一个景点,另一种是去下一个区域拿票.当时输入,写错了,卡了好长时间.... 代码如下: #pragma comment(linker, "/STACK:10240

POJ 2411 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

HDU 4906 Our happy ending (状压DP)

HDU 4906 Our happy ending 题目链接 题意:给定n个数字,每个数字可以是0-l,要选其中一些数字,然后使得和为k,问方案 思路:状压dp,滚动数组,状态表示第i个数字,能组成的数字状态为s的状态,然后每次一个数字,循环枚举它要选取1 - min(l,k)的多少,然后进行状态转移 代码: #include <cstdio> #include <cstring> typedef long long ll; const int N = (1<<20)

HDU 4856 Tunnels(BFS+状压DP)

HDU 4856 Tunnels 题目链接 题意:给定一些管道,然后管道之间走是不用时间的,陆地上有障碍,陆地上走一步花费时间1,求遍历所有管道需要的最短时间,每个管道只能走一次 思路:先BFS预处理出两两管道的距离,然后状态压缩DP求解,dp[s][i]表示状态s,停在管道i时候的最小花费 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using

HDU 5434 Peace small elephant 状压dp+矩阵快速幂

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: 108 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 小明很喜欢国际象棋,尤其喜欢国际象棋里面的大象(只要无阻挡能够斜着走任意格),但是他觉得国际象棋里的大象太凶残了,于是他

【计算几何】【状压dp】Codeforces Round #226 (Div. 2) D. Bear and Floodlight

读懂题意发现是傻逼状压. 只要会向量旋转,以及直线求交点坐标就行了.(验证了我这俩板子都没毛病) 细节蛮多. #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const double PI=acos(-1.0); #define EPS 0.00000001 struct Point { double x,y; Point(

HDU 5564 Clarke and digits 状压dp+矩阵加速

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5564 题意: 求长度在[L,R]范围,并且能整除7的整数的总数. 题解: 考虑最原始的想法: dp[i][j][k]表示长度为i,并且对7取模得到j的以k结尾的数. 则有状态转移方程dp[i+1][(h*10)+l)%7][k]+=dp[i][h][k'](k+k'!=K). 但是i范围是1~10^9,需要矩阵加速. 这里对dp[i][j][k]的[j][k]两个状态进行压缩,得到转移矩阵mat[

HDU 6006 Engineer Assignment:状压dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6006 题意: 在Google中,有个n项目,m个专家.第i个项目涉及c[i]个领域,分别为a[i][0]...a[i][c[i]-1].第i个专家精通d[i]个领域,分别为b[i][0]...b[i][d[i]-1]. 如果要完成一个项目,则这个项目所涉及到的每一个领域都必须至少有一个精通该领域的专家.你作为director,可以任意分配专家,但一个专家只能去做一个项目.问你最多能够完成多少个项目.

HDU 1074 Doing Homework(状压dp)

Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6299    Accepted Submission(s): 2708 Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a l