Cows POJ - 3348 凸包面积/Andrew凸包模板

Andrew似乎是Graham的上位替代?

反正15行的代码长度还是很有保存价值的

//#include<bits/stdc++.h>  
//#pragma comment(linker, "/STACK:1024000000,1024000000")   
#include<stdio.h>  
#include<algorithm>  
#include<queue>  
#include<string.h>  
#include<iostream>  
#include<math.h>  
#include<set>  
#include<map>  
#include<vector>  
#include<iomanip>  
using namespace std;  
  
const double pi=acos(-1.0);  
#define ll long long  
#define pb push_back

#define sqr(a) ((a)*(a))
#define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))

const int maxn=1e3+56;
const int inf=0x3f3f3f3f;

int n;

struct Point{
	double x,y;
	Point(){}
	Point(double x,double y):x(x),y(y){}
	Point operator+(const Point& rhs)const{return Point(x+rhs.x,y+rhs.y);}
	Point operator-(const Point& rhs)const{return Point(x-rhs.x,y-rhs.y);}
	Point operator*(const double d)const{return Point(d*x,d*y);}
	double cross(const Point &rhs)const{
		return (x*rhs.y-y*rhs.x);
	}
}point[maxn],vertex[maxn];

bool cmp_x(const Point a,const Point b){
	if(a.x==b.x)return a.y<b.y;
	else return a.x<b.x;
}

int Andrew(){		//返回凸包顶点数
	sort(point,point+n,cmp_x);
	int k=0;
	for(int i=0;i<n;i++){
		while(k>1 && (vertex[k-1]-vertex[k-2]).cross(point[i]-vertex[k-1])<=0)k--;
		vertex[k++]=point[i];
	}
	int m=k;
	for(int i=n-2;i>=0;i--){
		while(k>m && (vertex[k-1]-vertex[k-2]).cross(point[i]-vertex[k-1])<=0)k--;
		vertex[k++]=point[i];
	}
	if(k>1)k--;	//k=1凸包退化
	return k;
}

void solve(){		//求凸包面积,计算方式是凸包底边三角形的面积并
	int tot=Andrew();
	if(tot<=2){printf("0\n");return;}
	double area=0;
	for(int i=2;i<tot;i++){
		double a=dis(vertex[i-1],vertex[0]);
		double b=dis(vertex[i],vertex[0]);
		double c=dis(vertex[i],vertex[i-1]);
		double p=(a+b+c)/2;
		area+=sqrt(p*(p-a)*(p-b)*(p-c));
	}
	printf("%d\n",(int)(area/50.0));	//每头牛50平米面积
}

int main(){
	while(~scanf("%d",&n)){
		for(int i=0;i<n;i++){
			scanf("%lf%lf",&point[i].x,&point[i].y);
		}
		solve();
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值