BZOJ 1209: [HNOI2004]最佳包裹

一眼扫过去,凸包?数据范围什么这么小?

10分钟码完了Andrew,发现答案不对……

卧槽怎么是三维的。。。。。。。

三维凸包不会啊TAT

对着白书抄了一遍增量法,水过去了(你这样真的好吗

好吧回去再看一遍增量法,感觉很好玩的样子。

很想知道status里0MS的大爷是怎么做到的(随机增量?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstdlib>
using namespace std;
const double eps=1e-9;
const int N=100+5;
int dcmp(double x){
	if(fabs(x)<eps)return 0;
	return x<0?-1:1;
}
struct point{
	double x,y,z;
}p[N],p1[N];
point operator - (point a,point b){
	return (point){a.x-b.x,a.y-b.y,a.z-b.z};
}
point cross(point a,point b){
	return (point){a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x};
}
point cross(point a,point b,point c){
	return cross(b-a,c-a);
}
double dot(point a,point b){
	return a.x*b.x+a.y*b.y+a.z*b.z;
}
double sqr(double x){return x*x;}
double length(point p){
	return sqrt(sqr(p.x)+sqr(p.y)+sqr(p.z));
}
struct face{
	int v[3];
	point normal(point *p)const{
		return cross(p[v[0]],p[v[1]],p[v[2]]);
	}
	int cansee(point *p,int i)const{
		return dot(p[i]-p[v[0]],normal(p))>0;
	}
};
double rand01(){
	return rand()/(double)RAND_MAX;
}
double randeps(){
	return (rand01()-0.5)*eps;
}
point add_noise(point p){
	return (point){p.x+randeps(),p.y+randeps(),p.z+randeps()};
}
struct convexhull{
	vector<face>ch;
	bool vis[N][N];
	void increment(point *p,int n){
		memset(vis,0,sizeof(vis));
		for(int i=0;i<n;i++)p[i]=add_noise(p[i]);
		ch.clear();
		ch.push_back((face){{0,1,2}});
		ch.push_back((face){{2,1,0}});
		for(int i=3;i<n;i++){
			vector<face>tmp;tmp.clear();
			for(int j=0;j<ch.size();j++){
				face f=ch[j];
				int res=f.cansee(p,i);
				if(!res)tmp.push_back(f);
				for(int k=0;k<3;k++)vis[f.v[k]][f.v[(k+1)%3]]=res;
			}
			for(int j=0;j<ch.size();j++)
			for(int k=0;k<3;k++){
				int a=ch[j].v[k],b=ch[j].v[(k+1)%3];
				if(vis[a][b]!=vis[b][a]&&vis[a][b])
				tmp.push_back((face){a,b,i});
			}
			ch=tmp;
		}
	}
	double area(point a,point b,point c){
		return 0.5*length(cross(a,b,c));
	}
	double area(face f,point *p){
		return area(p[f.v[0]],p[f.v[1]],p[f.v[2]]);
	}
	double area(point *p){
		double ans=0;
		for(int i=0;i<ch.size();i++)
		ans+=area(ch[i],p);
		return ans;
	}
}sol;
int main(){
	//freopen("a.in","r",stdin);
	int n;scanf("%d",&n);
	for(int i=0;i<n;i++)scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
	for(int i=0;i<n;i++)p1[i]=p[i];
	sol.increment(p1,n);
	printf("%.6lf\n",sol.area(p));
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值