计算几何

理论:http://mindlee.net/2011/11/27/computational-geometry/

http://blog.chinaunix.net/uid-12127321-id-2957853.html


三角形的内心公式:


两直线交点:




//hdu 1392 凸包
#include <cstdio>
#include <algorithm>
#include <cmath>
const double esp=1e-8;
const long N=1100;
struct Point{
    double x,y;
}point[N],stack[N];
long n,top;
double Det(const Point &p1,const Point &p2,const Point &p3){
    return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);
}
double Dis(const Point &p1,const Point &p2){
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
int cmp(Point &a,Point &b){
    double k=Det(point[0],a,b);
    if (k>0 ||(k==0 && Dis(point[0],a)<Dis(point[0],b)))
        return 1;
    return 0;
}
void Convert(){
    for (long i=1;i<n;++i)
        if (point[i].y<point[0].y || (point[i].y==point[0].y && point[i].x<point[0].x)){
            Point temp=point[0]; point[0]=point[i]; point[i]=temp;
        }
    std::sort(point+1,point+n,cmp); 
    stack[0]=point[0]; stack[1]=point[1]; stack[2]=point[2]; top=2;
    for (long i=3;i<n;++i){
        while (Det(stack[top-1],stack[top],point[i])<=0 && top>=2)
            top--;
        stack[++top]=point[i];
    }
}
int main(){
    while (~scanf("%d",&n)&&n){
        for (long i=0;i<n;++i)
            scanf("%lf%lf",&point[i].x,&point[i].y);
        if (n==1){
            printf("0.00\n");
            continue;
        }
        if (n==2){
            printf("%.2lf\n",Dis(point[0],point[1]));
            continue;
        }
        Convert();
        double ans=0;
        for (long i=1;i<=top;++i) ans+=Dis(stack[i-1],stack[i]);
        ans+=Dis(stack[top],stack[0]);
        printf("%.2f\n",ans);
    }
    return 0;
}


//poj 1279 半平面交
#include <cstdio>
#include <cmath>
#define Exp 1e-8
const long N=1600;
struct Point{
	Point(double x=0.0,double y=0.0):x(x),y(y){}
	double x,y;
}point[N],p[N],q[N];
long n,pcnt,qcnt;
void init(){
	for (long i=1;i<=n;++i) p[i]=point[i];
	p[n+1]=point[1]; p[0]=point[n];
	pcnt=n; point[n+1]=point[1];
}
inline double Det(Point p1,Point p2,Point p3){
	return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);
}
inline Point Intersect(Point p1,Point p2,Point p3,Point p4){
	double s1,s2;
	Point temp;
	s1=Det(p1,p2,p3); s2=Det(p1,p2,p4);
	temp.x=(s1*p4.x-s2*p3.x)/(s1-s2);
	temp.y=(s1*p4.y-s2*p3.y)/(s1-s2);
	return temp;
}
void cut(Point p1,Point p2){
	qcnt=0;
	for (long i=1;i<=pcnt;++i)
		if (Det(p1,p2,p[i])<=Exp) q[++qcnt]=p[i];
		else{
			if (Det(p1,p2,p[i-1])<Exp) q[++qcnt]=Intersect(p1,p2,p[i],p[i-1]);
			if (Det(p1,p2,p[i+1])<Exp) q[++qcnt]=Intersect(p1,p2,p[i],p[i+1]);
		}
	for (long i=1;i<=qcnt;++i) p[i]=q[i];
	p[qcnt+1]=q[1]; p[0]=q[qcnt];
	pcnt=qcnt;
}
void solve(){
	init();
	for (long i=1;i<=n;++i)
		cut(point[i],point[i+1]);
}
inline double getArea(){
	//if (pcnt<=2) return 0.0;
	double ans=0.0;
	for (long i=1;i<=pcnt;++i)
		ans+=Det(Point(0.0,0.0),p[i],p[i+1])/2.0;
	return ans;
}
int main(){
	long t;
	scanf("%d",&t);
	while (t--){
		scanf("%d",&n);
		for (long i=1;i<=n;++i) scanf("%lf%lf",&point[i].x,&point[i].y);
		solve();
		/*if (pcnt==0) printf("NO\n");
		else printf("YES\n");*/
		printf("%.2f\n",fabs(getArea()));
	}
	return 0;
}


//poj 3714 分治法求最近点对
#include <cstdio>
#include <cmath>
#include <algorithm>
#define Exp 1e-8;
const double inf=1e100;
using namespace std;
const long N=620000;
struct Point{
	double x,y;
	bool flag;
}point[N];
long n,pt[N];
double Dis(Point p1,Point p2){
	if (p1.flag!=p2.flag)
		return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
	else return inf;
}
double solve(long l,long r){
	if (r==l+1) return Dis(point[l],point[r]);
	if (r==l+2) return min(min(Dis(point[l],point[l+1]),Dis(point[l],point[r])),
						Dis(point[l+1],point[r]));
	long m=(l+r)>>1,cnt=0,cnt_mid;
	double temp=min(solve(l,m),solve(m+1,r));
	if (temp==0) return 0;
	for (long i=m;point[m].x-point[i].x<temp && i>=l;--i)
		pt[++cnt]=i;
	cnt_mid=cnt;
	for (long i=m+1;point[i].x-point[m].x<temp && i<=r;++i)
		pt[++cnt]=i;
	for (long i=1;i<=cnt_mid;++i)
		for (long j=cnt_mid+1;j<=cnt;++j)
			temp=min(temp,Dis(point[pt[i]],point[pt[j]]));
	return temp;
}
long fuck(Point a,Point b){
	return a.x<b.x;
}
int main(){
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	long t; scanf("%d",&t);
	while (t--){
		scanf("%d",&n);
		for (long i=1;i<=n;++i){
			scanf("%lf%lf",&point[i].x,&point[i].y);
			point[i].flag=1;
		}
		for (long i=n+1;i<=2*n;++i){
			scanf("%lf%lf",&point[i].x,&point[i].y);
			point[i].flag=0;
		}
		n*=2;
		sort(point+1,point+1+n,fuck);
		printf("%.3f\n",solve(1,n));
	}
	return 0;
}


//poj3714 暴力法 最近点对
#include <cstdio>
#include <cmath>
#include <algorithm>
#define Exp 1e-8;
using namespace std;
const double inf=1e100;
const long N=610000;
struct Point{
	double x,y;
	int flag;
}point[N];
long n;
inline double Dis(Point p1,Point p2){
	if (p1.flag!=p2.flag)
		return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
	else 
		return inf;
}
long cmp(Point a,Point b){
	if (a.x==b.x && a.y<b.y) return 1;
	return a.x<b.x;
}
int main(){
	long t;
	scanf("%d",&t);
	while (t--){
		scanf("%d",&n);
		for (long i=1;i<=n;++i){
			scanf("%lf%lf",&point[i].x,&point[i].y);
			point[i].flag=1;
		}
		for (long i=n+1;i<=2*n;++i){
			scanf("%lf%lf",&point[i].x,&point[i].y);
			point[i].flag=0;
		}
		n*=2; 
		sort(point+1,point+1+n,cmp);
		double ans=inf;
		for (long i=1;i<n;++i)
			for (long j=i+1;j<=n;++j){
				ans=min(ans,Dis(point[i],point[j]));
				if (point[j].x-point[i].x>ans) 
					break;
			}
		printf("%.3f\n",ans);
	}
	return 0;
}


hdu4720 三角形的外心


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const double eps=1e-8;
struct Point{
	double x,y;
	Point(double x=0.0,double y=0.0):x(x),y(y){};
};

Point get_center(Point p1,Point p2,Point p3){
	Point C;
	double t1,t2,t3;
	t1=p1.x*p1.x+p1.y*p1.y-p2.x*p2.x-p2.y*p2.y;
	t2=p1.x*p1.x+p1.y*p1.y-p3.x*p3.x-p3.y*p3.y;
	t3=2*(p1.x-p2.x)*(p1.y-p3.y)-2*(p1.x-p3.x)*(p1.y-p2.y);
	C.x=((p1.y-p3.y)*t1-(p1.y-p2.y)*t2)/t3;
	C.y=-((p1.x-p3.x)*t1-(p1.x-p2.x)*t2)/t3;
	return C;
}

double dis(Point p1,Point p2){
	return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
}

int sgn(double x){
	return (x>eps)-(x<-eps);
}

Point p[10];
int t;
int main(){
	scanf("%d",&t);
	for (int k=1;k<=t;++k){
		for (int i=1;i<=4;++i) scanf("%lf%lf",&p[i].x,&p[i].y);
		Point C=get_center(p[1],p[2],p[3]);
		double R=dis(C,p[1]);
		for (int i=1;i<3;++i)
			for (int j=i+1;j<4;++j){
				Point tmp=Point((p[i].x+p[j].x)/2.0,(p[i].y+p[j].y)/2.0);
				double tmp_r=max(dis(tmp,p[6-i-j]),dis(p[i],p[j])/4);
				if (sgn(R-tmp_r)==1){
					C=tmp; R=tmp_r;
				}
			}
		double Dis=dis(p[4],C);
		if (sgn(Dis-R)==1) printf("Case #%d: Safe\n",k); 
		else printf("Case #%d: Danger\n",k); 
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值