现在的位置: 首页 > 综合 > 正文

神棍节献礼之——URAL1111 Squares(几何)

2013年09月20日 ⁄ 综合 ⁄ 共 2102字 ⁄ 字号 评论关闭

题意是有 N 个正方形,每个正方形给出一条对角线的两个顶点坐标,然后判断他们到指定点的距离的大小关系,按距离从近到远,升序输出这些正方形的编号。

注意,正方形的边可能不和坐标轴平行,还有如果指定点在正方形内部的话,距离认为是 0 。

方法很显然的,根据对角线的两点坐标计算出剩下的两个点,然后计算指定点到这个正方形(凸四边形)的距离,也就是计算点到线段的距离,并取最小值。

代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

const int N = 51;
const double MAX = 1e8;
const double eps = 1e-14;

struct point{
	double x,y;
};

struct square{
	point p1,p2;
	int id;
	double dist;
}s[N];

int dcmp(double x){
    if (x < -eps) return -1; 
	else return x > eps;
}

int cmp(square a,square b){
	if(dcmp(a.dist-b.dist)==0)return a.id < b.id;
	return dcmp(a.dist - b.dist)<0;
}

double min(double a,double b){
	if(dcmp(a-b)==1)return b;
	return a;
}
double max(double a,double b){
	if(dcmp(a-b)==1)return a;
	return b;
}

double dis(point a,point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double crossProduct(point a,point b,point c){//向量 ac 在 ab 的方向 
	return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);
}

int pin_convexh(point a,point p[]){//判断点a是否在凸多边形内
	int n=4;
	p[n] = p[0]; p[n+1] = p[1];
	for(int i=0; i<n; i++)
		if( dcmp(crossProduct(p[i],p[i+1],a)*crossProduct(p[i+1],p[i+2],a))==-1 )
			return 0;
	return 1;
}

double jobs(point p,point l1,point l2){//点 p 到线段 l1l2 的最小距离
	point t = p;
	t.x += l1.y - l2.y;  t.y += l2.x - l1.x;
	if( dcmp( crossProduct(l1,t,p)*crossProduct(l2,t,p) ) != -1 ) //包括点和线段共线 
		return dcmp(dis(p,l1)-dis(p,l2))==-1 ? dis(p,l1) : dis(p,l2);
	return fabs( crossProduct(p,l1,l2) )/dis(l1,l2);
}

point Whirl(double cosl, double sinl, point a, point b){//底边线段ab 绕a逆时针旋转角度A,b->b1,sinl是sinA的值   
	b.x -= a.x; b.y -= a.y;
    point c;
    c.x = b.x * cosl - b.y * sinl + a.x;
    c.y = b.x * sinl + b.y * cosl + a.y;
    return c;
}

double fun(point cent,square ss){
	point p[10],mid;
	mid.x=(ss.p1.x+ss.p2.x)/2.0; mid.y=(ss.p1.y+ss.p2.y)/2.0;
	p[0]=ss.p1;
	p[1]=Whirl(0,1,mid,p[0]);
	p[2]=ss.p2;
	p[3]=Whirl(0,1,mid,p[2]);
	if(pin_convexh(cent,p)==1)return 0.0;
	else {
		double min_dist=MAX;
		for(int i=0;i<4;i++)
			min_dist=min(jobs(cent,p[i],p[i+1]),min_dist);
		return min_dist;
	}
}

int main()
{
	point cent;
	int n,i;
	double a,b,c,d;
	while(~scanf("%d",&n)){
		for(i=1;i<=n;i++){
			scanf("%lf%lf%lf%lf",&s[i].p1.x,&s[i].p1.y,&s[i].p2.x,&s[i].p2.y);
			s[i].id=i;
		}
		scanf("%lf%lf",¢.x,¢.y);
		for(i=1;i<=n;i++)s[i].dist=fun(cent,s[i]);

		sort(s+1,s+n+1,cmp);

		printf("%d",s[1].id);
		for(i=2;i<=n;i++)printf(" %d",s[i].id);
		puts("");
	}
	return 0;
}

抱歉!评论已关闭.