2119. 最佳包裹

题目链接

2119. 最佳包裹

发强公司生产了一种金属制品,是由一些笔直的金属条连接起来的,金属条和别的金属条在交点上被焊接在了一起。

现在由于美观需要,在这个产品用一层特殊的材料包裹起来。

公司为了节约成本,希望消耗的材料最少(不计裁剪时的边角料的损失)。

编程,输入包括该产品的顶点的个数,以及所有顶点的坐标;请计算出包裹这个产品所需要的材料的最小面积。

结果要求精确到小数点后第六位(四舍五入)。

输入格式

输入文件由若干行组成:

1 行是一个整数 n,表示顶点的个数;第 2 行到第 n+1 行,每行是 3 个实数 xi,yi,zi,表示第 i 个顶点的坐标。

每个顶点的位置各不相同。

输出格式

输出文件只有一个实数,表示包裹一个该产品所需的材料面积的最小值。

数据范围

4n100

输入样例:

4 0 0 0 1 0 0 0 1 0 0 0 1

输出样例:

2.366025

解题思路

三维凸包

增量法:假设已经求出 1i1 的三维凸包,求解 1i 的三维凸包相当于将 i 这个点当作光源,照射 1i1 构成的凸包,照射后,处于背面的平面一定要留下来,同时那些边缘线也需要留下来与 i 这个点构成平面,线边缘线是正面和背面的交集,判断所有平面的直线是否同时处在正面和背面即可

另外,还需要处理四点共面的情况,在判断边缘线时,如果当前处理的点正好在四点共面的其中一个点上,则该边缘线可能判断不出来,不妨将所有点随机抖动一个微小的范围,这样四点共面的概率就会很小

由多面体的欧拉定理:+=2,设顶点数为 a,棱长数为 b,表面数为 c,对于一个平面来说其有三个点,即 a=3c,而对于一条边来说其有两个点,即 a=2b,即 对于一个平面都是三角形的多面体来说 bc 的关系为 3c=2b,代入公式得 b=3n6c=2n4,故:

  • 时间复杂度:O(n2)

代码

// Problem: 最佳包裹 // Contest: AcWing // URL: https://www.acwing.com/problem/content/2121/ // Memory Limit: 64 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=105; const double eps=1e-10; int n,m; bool g[N][N]; double rand_eps() { return ((double)rand()/RAND_MAX-0.5)*eps; } struct Point { double x,y,z; void shake() { x+=rand_eps(),y+=rand_eps(),z+=rand_eps(); } Point operator-(Point o) { return {x-o.x,y-o.y,z-o.z}; } Point operator*(Point o) { return {y*o.z-z*o.y,z*o.x-x*o.z,x*o.y-y*o.x}; } double operator&(Point o) { return x*o.x+y*o.y+z*o.z; } double len() { return sqrt(x*x+y*y+z*z); } }point[N]; struct Plane { int v[3]; Point norm() { return (point[v[1]]-point[v[0]])*(point[v[2]]-point[v[0]]); } double area() { return norm().len()/2; } bool above(Point a) { return ((a-point[v[0]])&norm())>=0; } }plane[N],np[N]; void get_convex_3d() { plane[++m]={1,2,3}; plane[++m]={3,2,1}; for(int i=4;i<=n;i++) { int cnt=0; for(int j=1;j<=m;j++) { bool t=plane[j].above(point[i]); if(!t)np[++cnt]=plane[j]; for(int k=0;k<3;k++) g[plane[j].v[k]][plane[j].v[(k+1)%3]]=t; } for(int j=1;j<=m;j++) for(int k=0;k<3;k++) { int a=plane[j].v[k],b=plane[j].v[(k+1)%3]; if(g[a][b]&&!g[b][a])np[++cnt]={a,b,i}; } m=0; for(int i=1;i<=cnt;i++)plane[++m]=np[i]; } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].z),point[i].shake(); get_convex_3d(); double res=0; for(int i=1;i<=m;i++)res+=plane[i].area(); printf("%.6lf",res); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16918570.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示