POJ 3528--Ultimate Weapon(三维凸包)
| Time Limit: 2000MS | Memory Limit: 131072K | |
| Total Submissions: 2430 | Accepted: 1173 |
Description
In year 2008 of the Cosmic Calendar, the Aliens send a huge armada towards the Earth seeking after conquest. The humans now depend on their ultimate weapon to retain their last hope of survival. The weapon, while capable of creating a continuous, closed and convex lethal region in the space and annihilating everything enclosed within, unfortunately exhausts upon each launch a tremendous amount of energy which is proportional to the surface area of the lethal region.
Given the positions of all battleships in the Aliens' armada, your task is to calculate the minimum amount of energy required to destroy the armada with a single launch of the ultimate weapon. You need to report the surface area of the lethal region only.
Input
The first line contains one number N -- the number of battleships.(1 ≤ N ≤ 500)
Following N lines each contains three integers presenting the position of one battleship.
Output
The minimal area rounded to three decimal places.
Sample Input
4
0 0 0
4 0 0
2 3 0
1 1 2
Sample Output
19.137
Hint
Source
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
const int N = ;
const double eps = 1e-;
typedef struct point3 {
double x, y, z;
point3() { }
point3(double a, double b, double c) :x(a), y(b), z(c) { }
point3 operator -(const point3 &b)const { //返回减去后的新点
return point3(x - b.x, y - b.y, z - b.z);
}
point3 operator +(const point3 &b)const { //返回加上后的新点
return point3(x + b.x, y + b.y, z + b.z);
}
//数乘计算
point3 operator *(const double &k)const { //返回相乘后的新点
return point3(x * k, y * k, z*k);
}
point3 operator /(const double &k)const { //返回相除后的新点
return point3(x / k, y / k, z / k);
}
double operator *(const point3 &b)const { //点乘
return (x*b.x + y*b.y + z*b.z);
}
point3 operator ^(const point3 &p) const { //叉积
return point3(y*p.z - p.y*z, z*p.x - x*p.z, x*p.y - y*p.x);
}
double vlen()const { //向量的模
return sqrt(x*x + y*y + z*z);
}
}point3;
struct fac {
int a, b, c;//凸包一个面上的三个点的编号
bool ok; //该面是否是最终凸包中的面
};
struct T3dhull {
int n; //初始点数
point3 ply[N]; //初始点
int trianglecnt; //凸包上三角形数
fac tri[N]; //凸包三角形可证明被创建的面不会超过6N
int vis[N][N]; //点i到点j是属于哪个面
double dist(point3 a) { return sqrt(a.x*a.x + a.y*a.y + a.z*a.z); } //两点长度
double area(point3 a, point3 b, point3 c){return dist((b - a) ^ (c - a));} //三角形面积*2 //返回四面体有向体积*6
//在储存面时,保证面的法线方向朝向凸包外部,如果在某一平面和点p所组成的四面体的有向体积为正,则p点在凸包外部,并且此点可以被p点看见。
double volume(point3 a, point3 b, point3 c, point3 d){
return ((b - a) ^ (c - a))* (d - a);
}
double ptoplane(point3 &p, fac &f){ //点到平面距离,体积法
point3 m = ply[f.b] - ply[f.a], n = ply[f.c] - ply[f.a], t = p - ply[f.a];
return (m^n) * t;
}
void deal(int p, int a, int b) {
int f = vis[a][b];
fac add;
if (tri[f].ok)
{
if ((ptoplane(ply[p], tri[f])) > eps)
dfs(p, f);
else
{
add.a = b, add.b = a, add.c = p, add.ok = ;
vis[p][b] = vis[a][p] = vis[b][a] = trianglecnt;
tri[trianglecnt++] = add;
}
}
}
void dfs(int p, int cnt) {//维护凸包,如果点p在凸包外侧则更新凸包
tri[cnt].ok = ;
deal(p, tri[cnt].b, tri[cnt].a);
deal(p, tri[cnt].c, tri[cnt].b);
deal(p, tri[cnt].a, tri[cnt].c);
}
bool same(int s, int e) {
point3 a = ply[tri[s].a], b = ply[tri[s].b], c = ply[tri[s].c];
return fabs(volume(a, b, c, ply[tri[e].a])) < eps
&& fabs(volume(a, b, c, ply[tri[e].b])) < eps
&& fabs(volume(a, b, c, ply[tri[e].c])) < eps;
}
void construct()//构造凸包
{
int i, j;
trianglecnt = ;
if (n<) return;
bool tmp = true;
for (i = ; i < n; i++) //前两点不共点
{
if ((dist(ply[] - ply[i])) > eps)
{
swap(ply[], ply[i]);
tmp = false;
break;
}
}
if (tmp)return;
tmp = true;
for (i = ; i < n; i++) //前三点不共线
{
if ((dist((ply[] - ply[]) ^ (ply[] - ply[i]))) > eps)
{
swap(ply[], ply[i]);
tmp = false;
break;
}
}
if (tmp) return;
tmp = true;
for (i = ; i < n; i++) //前四点不共面
{
if (fabs(((ply[] - ply[]) ^ (ply[] - ply[]))* (ply[] - ply[i]))>eps)
{
swap(ply[], ply[i]);
tmp = false;
break;
}
}
if (tmp)return;
fac add;
for (i = ; i < ; i++) //构建初始四面体
{
add.a = (i + ) % , add.b = (i + ) % , add.c = (i + ) % , add.ok = ;
if ((ptoplane(ply[i], add))>)
swap(add.b, add.c);
vis[add.a][add.b] = vis[add.b][add.c] = vis[add.c][add.a] = trianglecnt;
tri[trianglecnt++] = add;
}
for (i = ; i < n; i++) //构建更新凸包
{
for (j = ; j < trianglecnt; j++)
{
if (tri[j].ok && (ptoplane(ply[i], tri[j])) > eps)
{
dfs(i, j); break;
}
}
}
int cnt = trianglecnt;
trianglecnt = ;
for (i = ; i < cnt; i++)
{
if (tri[i].ok)
tri[trianglecnt++] = tri[i];
}
}
double area() //表面积
{
double ret = ;
for (int i = ; i < trianglecnt; i++)
ret += area(ply[tri[i].a], ply[tri[i].b], ply[tri[i].c]);
return ret / 2.0;
}
double volume()
{
point3 p(, , );
double ret = ;
for (int i = ; i < trianglecnt; i++)
ret += volume(p, ply[tri[i].a], ply[tri[i].b], ply[tri[i].c]);
return fabs(ret / );
}
}hull; int main() {
while (~scanf("%d", &hull.n)) {
int i;
for (i = ; i < hull.n; i++)
scanf("%lf %lf %lf", &hull.ply[i].x, &hull.ply[i].y, &hull.ply[i].z);
hull.construct();
printf("%.3lf\n", hull.area());
}
return ;
}
POJ 3528--Ultimate Weapon(三维凸包)的更多相关文章
- poj 3528 Ultimate Weapon (3D Convex Hull)
3528 -- Ultimate Weapon 一道三维凸包的题目,题目要求求出三维凸包的表面积.看懂了网上的三维凸包的代码以后,自己写的代码,跟网上的模板有所不同.调了一个晚上,结果发现错的只是数组 ...
- POJ 3528 求三维凸包表面积
也是用模板直接套的题目诶 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include < ...
- POJ 2225 / ZOJ 1438 / UVA 1438 Asteroids --三维凸包,求多面体重心
题意: 两个凸多面体,可以任意摆放,最多贴着,问他们重心的最短距离. 解法: 由于给出的是凸多面体,先构出两个三维凸包,再求其重心,求重心仿照求三角形重心的方式,然后再求两个多面体的重心到每个多面体的 ...
- 三维凸包求其表面积(POJ3528)
Ultimate Weapon Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 2074 Accepted: 989 D ...
- hdu4273Rescue(三维凸包重心)
链接 模板题已不叫题.. 三维凸包+凸包重心+点到平面距离(体积/点积) 体积-->混合积(先点乘再叉乘) #include <iostream> #include<cstd ...
- hdu4449Building Design(三维凸包+平面旋转)
链接 看了几小时也没看懂代码表示的何意..无奈下来问问考研舍友. 还是考研舍友比较靠谱,分分钟解决了我的疑问. 可能三维的东西在纸面上真的不好表示,网上没有形象的题解,只有简单"明了&quo ...
- hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***
新模板 /* HDU 4273 Rescue 给一个三维凸包,求重心到表面的最短距离 模板题:三维凸包+多边形重心+点面距离 */ #include<stdio.h> #include&l ...
- HDU 4573 Throw the Stones(动态三维凸包)(2013 ACM-ICPC长沙赛区全国邀请赛)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4573 Problem Description Remember our childhood? A fe ...
- POJ 2251 Dungeon Master --- 三维BFS(用BFS求最短路)
POJ 2251 题目大意: 给出一三维空间的地牢,要求求出由字符'S'到字符'E'的最短路径,移动方向可以是上,下,左,右,前,后,六个方向,每移动一次就耗费一分钟,要求输出最快的走出时间.不同L层 ...
随机推荐
- Redis学习笔记(二) ---- PHP操作Redis各数据类型
Redis 一.使用PHP操作Redis存储系统中的各类数据类型方法 1.String(字符串)操作 <?php // 1. 实例化 $redis = new Redis; // 2. 连接 r ...
- js-滚动到指定位置导航栏固定顶部
最近整理一下之前做的一个项目,把滚动条动态固定顶部的代码整理出来和大家分享,上代码 <!DOCTYPE html> <html> <head> <meta c ...
- require'模块化jquery和angular问题
require 模块化开发问题,正常自己写的模块 是exports 导出一个模块 //模块化引入jquery 不同和问题 require 引入jquery swiper .... 插件和库的时候需要 ...
- C# ——窗体和控件随着分辨率的变化自适应大小
一.说明 我们自己编写程序的界面,会遇到各种屏幕分辨 率,只有自适应才能显的美观.实际上,做到这点也很简单,就是首先记录窗体和它上面控件的初始位置和大小,当窗体改变比例时,其控件的位置和大小也按此比 ...
- vs2010开发activex(MFC)控件/ie插件(一)
原文:http://blog.csdn.net/yhhyhhyhhyhh/article/details/50782904 vs2010开发activex(MFC)控件: 第一步:生成ac ...
- 记重回IT行业的面试
问点: 0,梳理一个前端知识框架 1,jQuery的理解 2,仿某网站首页,除了download,显示新优化地方 3,文档模型(DOM) 事件流 事件处理程序 事件类型 例如阻止冒泡的方法 4,前端跟 ...
- SQL Server ->> Sparse File(稀疏文件)
Sparse File(稀疏文件)不是SQL Server的特性.它属于Windows的NTFS文件系统的一个特性.如果某个大文件中的数据包含着大量“0数据”(这个应该从二进制上看),这样的文件就可以 ...
- yii2.0中url重写实现方法
在yii框架里有前台和后台页面,举例前台url重写. 控制器与路由 控制器以Controller作为后缀,继承自yii\web\Controller; 动作以action作为前缀,public访问修饰 ...
- (名词 形容词 动词 副词)重读&(冠词 介词 连词 代词 辅助词(Be))弱读
二,一些发音规则 除了上面的练习之外,这里还有几个注意点需要我们有足够的认识,那就是英语有重读.弱读.连读.爆破.语感(节奏和断句)等(其实当你跟读并背诵新概念之后,这一切都是神马,你不知觉地也会发现 ...
- OWASP出品:Xenotix XSS漏洞测试框架及简单使用
OWASP Xenotix XSS Exploit Framework是一个高效的跨站脚本漏洞(XSS)检测和攻击测试框架.它通过特有的三大浏览器引擎(包括Trident, WebKit和Gecko) ...