`

hdu3662

阅读更多

source: http://acm.hdu.edu.cn/showproblem.php?pid=3662

title     : 3D Convex Hull

eclipse C++ 编译通过

 

#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <list>
using namespace std;
const double eps = 1e-8;
typedef list<int>::iterator liit;
inline int sign(double d){
	if(d < -eps) return -1;
	return (d > eps) ? 1 : 0;
}
struct point{
	double x, y, z;
	point(double _x=0, double _y=0, double _z=0):x(_x), y(_y), z(_z) {}
	void read(){ scanf("%lf%lf%lf", &x, &y, &z); }
	bool operator==(const point& tp){
		return (!sign(x-tp.x)) && (!sign(y-tp.y)) && (!sign(z-tp.z));
	}
	bool isOrg(){
		return !sign(x) && !sign(y) && !sign(z);
	}
	point operator-(point tp){
		return point(x-tp.x, y-tp.y, z-tp.z);
	}
};
struct face{
	list<int> pos;
	point v;  //法向量
	double d; //常量
};
inline bool cmp(point p1, point p2){
	return (p1.x < p2.x) || (p1.x == p2.x && p1.y < p2.y)
		|| (p1.x == p2.x && p1.y == p2.y && p1.z < p2.z);
}
//向量st-->ed1和st-->ed2的叉积
inline point xmul3d(point st, point ed1, point ed2){
	ed1 = ed1 - st;
	ed2 = ed2 - st;
	return point(ed1.y*ed2.z-ed2.y*ed1.z, ed1.z*ed2.x-ed2.z*ed1.x,
		ed1.x*ed2.y-ed2.x*ed1.y);
}
//向量(0,0)-->p1和(0,0)-->ed2的叉积
inline double dmul3d(point p1, point p2){
	return p1.x*p2.x+p1.y*p2.y+p1.z*p2.z;
}
inline double dist3d(point p1, point p2){
	return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y)
		+ (p1.z-p2.z)*(p1.z-p2.z));
}
//三维凸包类
struct convex3d{
	static const int N = 305;  //点的数目的最大值
	point ps[N];       //求解凸包的点集
	list<face> convex; //convex存储三维的凸包的各个面,这些面是三维空间的凸多边形
	int pn;            //点的个数
	int fsign[N][N];
	//添加由ps里的第a,b,c个点组成的面
	void addFace(int a, int b, int c){
		face tf;
		tf.pos.push_back(a);
		tf.pos.push_back(b);
		tf.pos.push_back(c);
		tf.v = xmul3d(ps[a], ps[b], ps[c]);
		tf.d = -dmul3d(ps[a], tf.v);
		convex.push_back(tf);
	}
	//插入第i个点是,对面f进行处理
	int handleFace(face f, int i){
		int s = sign(dmul3d(f.v, ps[i]) + f.d);
		liit now, nxt;
		now = f.pos.begin();
		nxt = f.pos.begin();
		nxt++;
		for(; nxt != f.pos.end(); nxt++, now++){
			fsign[*now][*nxt] = s;
		}
		fsign[*now][*f.pos.begin()] = s;
		return s;
	}
	//判断第i个点是否在f里面
	bool inFace(face f, int i){
		liit now, nxt;
		int pn, nn, s;
		now = f.pos.begin();
		nxt = f.pos.begin();
		nxt++;
		for(pn = nn = 0; nxt != f.pos.end(); nxt++, now++){
			s = sign(dmul3d(xmul3d(ps[*now], ps[*nxt], ps[i]), f.v));
			if(s == 1) pn++;
			else if(s == -1) nn++;
		}
		s = sign(dmul3d(xmul3d(ps[*now], ps[*f.pos.begin()], ps[i]), f.v));
		if(s == 1) pn++;
		else if(s == -1) nn++;
		if(pn >= 1 && nn >= 1) return false;
		return true;
	}
	//扩展面f,返回true表示需要删除当前的面
	bool extFace(face& f, int i){
		liit now, nxt;
		bool flag = false;
		now = f.pos.begin();
		nxt = f.pos.begin();
		nxt++;
		if(fsign[*now][*nxt] == 0){
			list<int> tpos;
			while(true){
				if(sign(dmul3d(xmul3d(ps[i], ps[*now], ps[*nxt]), f.v)) >= 1){
					break;
				}
				now++;
				if(now == f.pos.end()) now = f.pos.begin();
				nxt++;
				if(nxt == f.pos.end()) nxt = f.pos.begin();
			}
			tpos.push_back(*now);
			int st = *now;
			while(*nxt != st){
				if(sign(dmul3d(xmul3d(ps[*now], ps[i], ps[*nxt]), f.v)) >= 0){
					break;
				}
				tpos.push_back(*nxt);
				now++;
				if(now == f.pos.end()) now = f.pos.begin();
				nxt++;
				if(nxt == f.pos.end()) nxt = f.pos.begin();
			}
			tpos.push_back(i);
			while(true){
				now++;
				if(now == f.pos.end()) now = f.pos.begin();
				nxt++;
				if(nxt == f.pos.end()) nxt = f.pos.begin();
				if(*now == st) break;
				if(sign(dmul3d(xmul3d(ps[i], ps[*now], ps[*nxt]), f.v)) >= 1){
					tpos.push_back(*now);
				}
			}
			f.pos = tpos;

		}else if(fsign[*now][*nxt] > 0){
			for(; nxt != f.pos.end(); now++, nxt++){
				if(fsign[*nxt][*now] < 0){
					addFace(*now, *nxt, i);
				}
			}
			if(fsign[*f.pos.begin()][*now] < 0){
				addFace(*now, *f.pos.begin(), i);
			}
			flag = true;
		}
		return flag;
	}
	//对ps里的pn个点求最小包围多面体,结果放在convex中
	void initConvex(){
		sort(ps, ps+pn, cmp);
		pn = unique(ps, ps+pn) - ps;
		convex.clear();
		if(pn <= 2){
			return;
		}
		int a, b, c;
		double ab, bc, ac;
		a = 0;
		b = 1;
		for(c = 2; c < pn; c++){
			ab = dist3d(ps[a], ps[b]);
			bc = dist3d(ps[b], ps[c]);
			ac = dist3d(ps[a], ps[c]);
			if(sign(ab+bc-ac) == 0){
				b = c;
			}else if(sign(ab+ac-bc) == 0){
				a = c;
			}else if(sign(ac+bc-ab) != 0){
				break;
			}
		}
		if(c == pn){
			return;
		}
		int i, size, j;
		list<face>::iterator it;
		addFace(a, b, c);
		addFace(a, c, b);
		for(i = c+1; i < pn; i++){
			size = convex.size();
			for(it = convex.begin(), j = 0; j < size; j++, it++){
				if(handleFace(*it, i) == 0 && inFace(*it, i)){
						break;
				}
			}
			if(j < size) continue;
			for(it = convex.begin(), j = 0; j < size; j++){
				if(extFace(*it, i)){
					it = convex.erase(it);
				}else{
					it++;
				}
			}
		}
	}
};
convex3d c;
int main(){
#ifndef ONLINE_JUDGE
   // freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif
    while(~scanf("%d", &c.pn)){
        int i;
        for(i = 0; i < c.pn; i++) c.ps[i].read();
        c.initConvex();
        printf("%d\n", c.convex.size());
    }
    return 0;
}
 
分享到:
评论

相关推荐

    hdu.rar_hdu

    HDU(杭州电子科技大学在线评测系统)是一个深受程序员喜爱的在线编程练习平台,它提供了丰富的算法题目供用户挑战,帮助他们提升编程技能和算法理解能力。"hdu.rar_hdu"这个压缩包文件很可能是某位程序员整理的他在...

    HDU_2010.rar_hdu 2010_hdu 20_hdu acm20

    【标题】"HDU_2010.rar"是一个压缩包文件,其中包含了与"HDU 2010"相关的资源,特别是针对"HDU ACM20"比赛的编程题目。"hdu 2010"和"hdu 20"可能是该比赛的不同简称或分类,而"hdu acm20"可能指的是该赛事的第20届...

    HDU题目java实现

    【标题】"HDU题目java实现"所涉及的知识点主要集中在使用Java编程语言解决杭州电子科技大学(HDU)在线评测系统中的算法问题。HDU是一个知名的在线编程竞赛平台,它提供了大量的算法题目供参赛者练习和提交解决方案...

    ACM HDU题目分类

    ACM HDU 题目分类 ACM HDU 题目分类是指对 HDU 在线判题系统中题目的分类,总结了大约十来个分类。这些分类将有助于编程选手更好地理解和解决问题。 DP 问题 DP(Dynamic Programming,动态规划)是一种非常重要...

    hdu1250高精度加法

    ### hdu1250高精度加法 #### 背景介绍 在计算机科学与编程竞赛中,处理大整数运算(特别是加法、减法、乘法等)是常见的需求之一。当数字的位数超过了标准数据类型(如`int`、`long`等)所能表示的最大值时,就需要...

    hdu.rar_HDU 1089.cpp_OJ题求和_hdu_horsekw5_杭电obj

    【标题】"hdu.rar_HDU 1089.cpp_OJ题求和_hdu_horsekw5_杭电obj" 提供的信息是关于一个压缩文件,其中包含了一个名为 "HDU 1089.cpp" 的源代码文件,这个文件是为了解决杭州电子科技大学(Hangzhou Dianzi ...

    HDU DP动态规划

    【标题】"HDU DP动态规划"涉及到的是在算法领域中的动态规划(Dynamic Programming,简称DP)技术,这是解决复杂问题的一种高效方法,尤其适用于有重叠子问题和最优子结构的问题。动态规划通常用于优化多阶段决策...

    HDU1059的代码

    HDU1059的代码

    hdu1001解题报告

    hdu1001解题报告

    hdu 1574 passed sorce

    hdu 1574 passed sorce

    ACM HDU

    【ACM HDU】指的是在ACM(国际大学生程序设计竞赛,International Collegiate Programming Contest)中,参赛者在杭州电子科技大学(Hangzhou Dianzi University,简称HDU)的在线评测系统上完成并已解决的题目集合...

    hdu2101解决方案

    hdu2101AC代码

    杭电ACMhdu1163

    【标题】:杭电ACMhdu1163 【描述】:这是一道源自杭州电子科技大学(Hangzhou Dianzi University,简称HDU)的ACM编程竞赛题目,编号为1163。这类问题通常需要参赛者利用计算机编程解决数学、逻辑或算法上的挑战,...

    HDU.rar_hdu_hdu07_com_shownv9b_www.563hdu.

    【标题】"HDU.rar_hdu_hdu07_com_shownv9b_www.563hdu." 暗示这是一个与HDU(杭州电子科技大学在线编程平台)相关的压缩包,其中可能包含了该平台上的编程竞赛题目或练习题目的源代码。"hdu07"可能是某个特定题目的...

    Hdu1000—2169部分代码

    HDU是杭州电子科技大学(Hangzhou Dianzi University)举办的一个在线编程竞赛平台,全称为HDU Online Judge。ACM是国际大学生程序设计竞赛(International Collegiate Programming Contest)的缩写,是一个全球性的...

    hdu 5007 Post Robot

    hdu 5007 Post Robot 字符串枚举。 暴力一下就可以了。

    HDU acm-PPT课件

    【ACM入门与提高:HDU ACM竞赛课程详解】 ACM(国际大学生程序设计竞赛,International Collegiate Programming Contest,简称ICPC或ACM/ICPC)是一项全球性的竞赛,旨在激发大学生对计算机科学的兴趣,提升他们的...

    hdu_acm_1084.rar_ACM_HDU10_acm10_hdu_hdu 1084

    【标题】"hdu_acm_1084.rar_ACM_HDU10_acm10_hdu_hdu 1084" 提供的是一个关于杭电(HDU)ACM竞赛第1084题的解决方案。该题目可能是在编程竞赛中常见的算法问题,而ACM(国际大学生程序设计竞赛)是全球知名的编程...

    HDU最全ac代码

    HDU(Hangzhou Dianzi University)是国内外知名的在线编程竞赛平台,主要服务于ACM/ICPC(国际大学生程序设计竞赛)以及相关的算法训练。"HDU最全ac代码"这个压缩包很可能是包含了在HDU平台上解题通过的完整源代码...

    hdu动态规划算法集锦

    根据提供的信息,我们可以总结出以下关于“hdu动态规划算法集锦”的知识点: ### 动态规划基础概念 动态规划是一种解决多阶段决策问题的方法,它通过将原问题分解为互相重叠的子问题,利用子问题的解来构建原问题...

Global site tag (gtag.js) - Google Analytics