1209: [HNOI2004]最佳包裹

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 160  Solved: 58
[Submit][Status][Discuss]

Description

H
公司生产了一种金属制品,是由一些笔直的金属条支撑起来的,金属条和别的金属条在交点上被焊接在了一起。现在由于美观需要,在这个产品用一层特殊的材料包
裹起来。公司为了节约成本,希望消耗的材料最少(不计裁剪时的边角料的损失)。你的程序需要根据给定的输入,给出符合题意的输出:
输入包括该产品的顶点的个数,以及所有顶点的坐标; 你需要根据输入的计算出包裹这个产品所需要的材料的最小面积。
结果要求精确到小数点后第六位。(四舍五入)

Input

第1行是一个整数n(4 <= n <= 100),表示顶点的个数;第2行到第n+1行,每行是3个实数xi,yi,zi,表示第i个顶点的坐标。每个顶点的位置各不相同。

Output

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

Sample Input

4
0 0 0
1 0 0
0 1 0
0 0 1 说明:该输入示例中共有4个点,可参见后面的图示。

Sample Output

2.366025

HINT

  这道题算是三维凸包的模板题吧,话说网上的三维凸包的教程中判三点共线,四点共面的方法确实有些复杂,经过idy博客的启发,其实在做凸包前对每个点加一遍噪音就行了。如果一个点可以看见当前一个面,那么这个面就会被删除,其表现就是有向体积为负数,删除一个面的同时,删除这个面的三条边(也是有向的)最有扫一遍观察哪些边的反向边不存在,然后将他们的反向边与当前加的点一同构成新的凸包。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<assert.h>
#include<vector>
using namespace std;
#define MAXN 120
#define eps 1e-11
typedef double real;
inline int sgn(real x)
{
if (abs(x)<eps)return ;
return x<?-:;
}
struct point
{
real x,y,z;
point(real x,real y,real z):x(x),y(y),z(z){}
point(){}
int read()
{
return scanf("%lf %lf %lf\n",&x,&y,&z);
}
void noise()
{
x+=(real)(rand()%-)/*eps;
y+=(real)(rand()%-)/*eps;
z+=(real)(rand()%-)/*eps;
}
real len()
{
return sqrt(x*x+y*y+z*z);
}
};
typedef point vect;
struct line
{
point ps;
real x,y,z;
line(){}
line(point p1,point p2)
{
ps=p1;
x=p2.x-p1.x;
y=p2.y-p1.y;
z=p2.z-p1.z;
}
line(point ps,real x,real y,real z):ps(ps),x(x),y(y),z(z){}
};
vect xmul(line l1,line l2)
{
return vect(l1.y*l2.z-l1.z*l2.y,l1.z*l2.x-l1.x*l2.z,l1.x*l2.y-l1.y*l2.x);
}
real volume(line l1,line l2,line l3)
{
return + l1.x*l2.y*l3.z - l1.x*l2.z*l3.y
- l1.y*l2.x*l3.z + l1.y*l2.z*l3.x
+ l1.z*l2.x*l3.y - l1.z*l2.y*l3.x;
}
//+1 2 3
//-1 3 2
//-2 1 3
//+2 3 1
//+3 1 2
//-3 2 1
struct surface
{
point ps;
real x1,y1,z1;
real x2,y2,z2;
surface(){}
surface(point p1,point p2,point p3)
{
ps=p1;
x1=p2.x-p1.x,y1=p2.y-p1.y,z1=p2.z-p1.z;
x2=p3.x-p1.x,y2=p3.y-p1.y,z2=p3.z-p1.z;
}
real volume(point pt)
{
return ::volume(line(ps,pt),line(ps,x1,y1,z1),line(ps,x2,y2,z2));
}
vect nvect()
{
return xmul(line(ps,x1,y1,z1),line(ps,x2,y2,z2));
}
void reverse()
{
swap(x1,x2);
swap(y1,y2);
swap(z1,z2);
}
};
point pl[MAXN];
struct face
{
int pt[];
face(int x,int y,int z)
{
pt[]=x;pt[]=y;pt[]=z;
}
surface ToSurface()
{
return surface(pl[pt[]],pl[pt[]],pl[pt[]]);
}
void print()
{
printf("Face:%d %d %d\n",pt[],pt[],pt[]);
}
};
vector<face> cc;
vector<pair<int,int> > chs;
bool status[MAXN][MAXN];
int main()
{
freopen("input.txt","r",stdin);
int n;
scanf("%d",&n);
for (int i=;i<n;i++)
pl[i].read();
for (int i=;i<n;i++)
pl[i].noise();
/* for (int i=0;i<n;i++)
swap(pl[rand()%n],pl[rand()%n]);*/
cc.push_back(face(,,));
cc.push_back(face(,,));
for (int i=;i<;i++)
status[i][(i+)%]=true;
for (int i=;i<;i++)
status[i%][i-]=true;
for (int i=;i<n;i++)
{
//for (int j=0;j<cc.size();j++)cc[j].print(); printf("\n");
chs.clear();
for (int j=;j<cc.size();j++)
{
if (cc[j].ToSurface().volume(pl[i])<)
{
for (int k=;k<;k++)
{
status[cc[j].pt[k]][cc[j].pt[(k+)%]]=false;
chs.push_back(make_pair(cc[j].pt[k],cc[j].pt[(k+)%]));
}
swap(cc[j],cc[cc.size()-]);
cc.pop_back();
j--;
}
}
for (int j=;j<chs.size();j++)
{
if (!status[chs[j].first][chs[j].second] && status[chs[j].second][chs[j].first])continue;
chs[j]=chs[chs.size()-];
j--;
chs.pop_back();
}
for (int j=;j<chs.size();j++)
{
cc.push_back(face(i,chs[j].first,chs[j].second));
status[i][chs[j].first]=status[chs[j].first][chs[j].second]=status[chs[j].second][i]=true;
}
for (int j=;j<n;j++)
for (int k=;k<n;k++)
assert(!(status[j][k]^status[k][j]));
}
//for (int j=0;j<cc.size();j++)cc[j].print(); printf("\n");
real ans=;
for (int i=;i<cc.size();i++)
ans+=cc[i].ToSurface().nvect().len()/;
printf("%.6lf\n",abs(ans));
}

bzoj 1209: [HNOI2004]最佳包裹 三维凸包的更多相关文章

  1. BZOJ1209 [HNOI2004]最佳包裹 三维凸包 计算几何

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1209 题目概括 给出立体的n个点.求三维凸包面积. 题解 增量法,看了一天,还是没有完全懂. 上板 ...

  2. 洛谷P2287 [HNOI2004]最佳包裹(三维凸包)

    题面 传送门 题解 左转板子,调个精度就能\(A\)了 //minamoto #include<bits/stdc++.h> #define R register #define fp(i ...

  3. BZOJ1209 最佳包裹 (三维凸包 增量法)

    题意 求三维凸包的表面积. N≤100N\le100N≤100 题解 暴力往当前的凸包里加点.O(n2)O(n^2)O(n2).题解详见大佬博客 扰动函数shakeshakeshake是为了避免四点共 ...

  4. bzoj 1964: hull 三维凸包 计算几何

    1964: hull 三维凸包 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 54  Solved: 39[Submit][Status][Discuss ...

  5. bzoj 1209

    三维凸包裸题. 1.通过volume计算有向体积,判断点与面的位置关系. 2.噪声 /********************************************************* ...

  6. POJ 2225 / ZOJ 1438 / UVA 1438 Asteroids --三维凸包,求多面体重心

    题意: 两个凸多面体,可以任意摆放,最多贴着,问他们重心的最短距离. 解法: 由于给出的是凸多面体,先构出两个三维凸包,再求其重心,求重心仿照求三角形重心的方式,然后再求两个多面体的重心到每个多面体的 ...

  7. hdu4273Rescue(三维凸包重心)

    链接 模板题已不叫题.. 三维凸包+凸包重心+点到平面距离(体积/点积)  体积-->混合积(先点乘再叉乘) #include <iostream> #include<cstd ...

  8. hdu4449Building Design(三维凸包+平面旋转)

    链接 看了几小时也没看懂代码表示的何意..无奈下来问问考研舍友. 还是考研舍友比较靠谱,分分钟解决了我的疑问. 可能三维的东西在纸面上真的不好表示,网上没有形象的题解,只有简单"明了&quo ...

  9. hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***

    新模板 /* HDU 4273 Rescue 给一个三维凸包,求重心到表面的最短距离 模板题:三维凸包+多边形重心+点面距离 */ #include<stdio.h> #include&l ...

随机推荐

  1. Android(java)学习笔记151: SurfaceView使用

    1.SurfaceView简介       在一般的情况下,应用程序的View都是在相同的GUI线程(UI主线程)中绘制的.这个主应用程序线程同时也用来处理所有的用户交互(例如,按钮单击或者文本输入) ...

  2. 关于ASPOSE.WORD使用上的一个小问题

    最近实习期间负责了公司某个项目的一个功能模块里面的word导出功能,使用的是ASPOSE.WORD类库,但是经常导出时候会遇到图中的问题,大概意思就是两个表格不能跨在一起,调试了好几次还是没发现具体的 ...

  3. Web电子商务网(三层)V2.0源码

    Web电子商务网(三层)V2.0源码 源码描述: 一.源码特点     采用三层架构开发,购物车功能 二.功能介绍 前台集成了产品在线展示,用户注册.在线调查.在线投稿 后台有类别管理\图书管理\订单 ...

  4. 关于ContentProvider的批量操作

    今天看公司代码,发现在批量插入通话记录和联系人的时候,用了一个 ArrayList<ContentProviderOperation> ops = new ArrayList<Con ...

  5. MVC小系列(十八)【给checkbox和radiobutton添加集合的重载】

    mvc对DropDownListFor的重载很多,但对checkbox和radiobutton没有对集合的重载 所以该讲主要针对集合的扩展: #region 复选框扩展 /// <summary ...

  6. 注册dll

    unit Unit1; interface uses  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, Syste ...

  7. Ajax实现页面后台button click事件无刷新弹窗

    很多人在做链接弹出新窗口的时候,都习惯用Response.Wrtite("<script>window.open('a.aspx')</script>") ...

  8. oracle 11g不能连接报ORA-12537+ora-609解决

    操作系统: windows2008 数据库:oracle11g 问题发生:一套正常跑了一年的应用系统,忽然无法连接上数据库,但是另外一个应用可以正常链接,数据入库正常. 数据库服务器端查看: 使用 l ...

  9. 引用传递&值传递

    下面的程序阐述了值传递与应用传递的区别. package com.liaojianya.chapter1; /** * This program demonstrates the use of arr ...

  10. (hdu)5546 Ancient Go

    Problem Description Yu Zhou likes to play Go with Su Lu. From the historical research, we found that ...