hdu 2857 求点关于线段的对称点
本来很简单的一个题,但是有个大坑:
因为模板中Tline用到了直线的一般方程ax+by+c=0,所以有种很坑的情况需要特判:
斜率不存在啊喂
老子坑了一下午2333
#include <math.h>
#include <stdio.h> #define eps 1e-6
#define PI acos(-1.0)//3.14159265358979323846
//判断一个数是否为0,是则返回true,否则返回false
#define zero(x)(((x)>0?(x):-(x))<eps)
//返回一个数的符号,正数返回1,负数返回2,否则返回0
#define _sign(x)((x)>eps?1:((x)<-eps?2:0)) struct point
{
double x,y;
point(){}
point(double xx,double yy):x(xx),y(yy)
{}
};
struct line
{
point a,b;
line(){} //默认构造函数
line(point ax,point bx):a(ax),b(bx)
{}
};//直线通过的两个点,而不是一般式的三个系数
struct TLine
{
double a,b,c;
TLine(){}
TLine(double _a,double _b,double _c):a(_a),b(_b),c(_c)
{}
};//直线一般式的三个系数ax+by+c=0
struct TPoint
{
double x,y;
TPoint(){}
TPoint(double _x,double _y):x(_x),y(_y)
{}
TPoint operator-(TPoint&a)
{
TPoint p1;
p1.x=x-a.x;
p1.y=y-a.y;
return p1;
}
}; //求矢量[p0,p1],[p0,p2]的叉积
//p0是顶点
//若结果等于0,则这三点共线
//若结果大于0,则p0p2在p0p1的逆时针方向
//若结果小于0,则p0p2在p0p1的顺时针方向
double xmult(point p1,point p2,point p0)
{
return(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
//计算dotproduct(P1-P0).(P2-P0)
double dmult(point p1,point p2,point p0)
{
return(p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}
//两点距离
double distance(point p1,point p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
//判三点共线
int dots_inline(point p1,point p2,point p3)
{
return zero(xmult(p1,p2,p3));
}
//判点是否在线段上,包括端点
int dot_online_in(point p,line l)
{
return zero(xmult(p,l.a,l.b))&&(l.a.x-p.x)*(l.b.x-p.x)<eps&&(l.a.y-p.y)*(l.b.y-p.y)<eps;
}
//判点是否在线段上,不包括端点
int dot_online_ex(point p,line l)
{
return dot_online_in(p,l)&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y))&&(!zero(p.x-l.b.x)||!zero(p.y-l.b.y));
}
//判两点在线段同侧,点在线段上返回0
int same_side(point p1,point p2,line l)
{
return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>eps;
}
//判两点在线段异侧,点在线段上返回0
int opposite_side(point p1,point p2,line l)
{
return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)<-eps;
}
//判两直线平行
int parallel(line u,line v)
{
return zero((u.a.x-u.b.x)*(v.a.y-v.b.y)-(v.a.x-v.b.x)*(u.a.y-u.b.y));
}
//判两直线垂直
int perpendicular(line u,line v)
{
return zero((u.a.x-u.b.x)*(v.a.x-v.b.x)+(u.a.y-u.b.y)*(v.a.y-v.b.y));
}
//判两线段相交,包括端点和部分重合
int intersect_in(line u,line v)
{
if(!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))
return!same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);
return dot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u);
}
//判两线段相交,不包括端点和部分重合
int intersect_ex(line u,line v)
{
return opposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u);
}
//计算两直线交点,注意事先判断直线是否平行!
//线段交点请另外判线段相交(同时还是要判断是否平行!)
point intersection(line u,line v)
{
point ret=u.a;
double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));
ret.x+=(u.b.x-u.a.x)*t;
ret.y+=(u.b.y-u.a.y)*t;
return ret;
}
/*
//点到直线上的最近点
point ptoline(point p,line l)
{
point t=p;
t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
return intersection(p,t,l.a,l.b);
}
//点到直线距离
double disptoline(point p,line l)
{
return fabs(xmult(p,l.a,l.b))/distance(l.a,l.b);
}
//点到线段上的最近点
point ptoseg(point p,line l)
{
point t=p;
t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
if(xmult(l.a,t,p)*xmult(l.b,t,p)>eps)
return distance(p,l.a)<distance(p,l.b)?l.a:l.b;
return intersection(p,t,l.a,l.b);
}
//点到线段距离
double disptoseg(point p,line l)
{
point t=p;
t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
if(xmult(l.a,t,p)*xmult(l.b,t,p)>eps)
return distance(p,l.a)<distance(p,l.b)?distance(p,l.a):distance(p,l.b);
return fabs(xmult(p,l.a,l.b))/distance(l.a,l.b);
}
*/
//求p1关于p2的对称点
TPoint symmetricalPoint(TPoint p1,TPoint p2)
{
TPoint p3;
p3.x=*p2.x-p1.x;
p3.y=*p2.y-p1.y;
return p3;
}
//p点关于直线L的对称点
TPoint symmetricalPointofLine(TPoint p,TLine L)
{
TPoint p2;
double d;
d=L.a*L.a+L.b*L.b;
p2.x=(L.b*L.b*p.x-L.a*L.a*p.x-*L.a*L.b*p.y-*L.a*L.c)/d;
p2.y=(L.a*L.a*p.y-L.b*L.b*p.y-*L.a*L.b*p.x-*L.b*L.c)/d;
return p2;
} int main()
{
int T;
double X1,Y1,X2,Y2,Xs,Ys,Xe,Ye;
scanf("%d",&T);
while (T--)
{
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&X1,&Y1,&X2,&Y2,&Xs,&Ys,&Xe,&Ye);
double ta=(Y2-Y1)/(X2-X1),tc=Y2-ta*X2;
point A,B;
if (zero(X2-X1))
{
A=point(Xs,Ys);
if (Xe-X1>=) B=point(X1-fabs(Xe-X1),Ye);
else if (Xe-X1<) B=point(X1+fabs(Xe-X1),Ye);
}
else
{
TLine tl=TLine(ta,-,tc);
TPoint pt=TPoint(Xe,Ye);
TPoint tp=symmetricalPointofLine(pt,tl); A=point(tp.x,tp.y);
B=point(Xs,Ys);
}
line L1=line(A,B);
line L2=line(point(X1,Y1),point(X2,Y2));
point ans=intersection(L1,L2);
if (zero(ans.x)) ans.x=;
if (zero(ans.y)) ans.y=;
printf("%.3lf %.3lf\n",ans.x,ans.y);
} return ;
}
hdu 2857 求点关于线段的对称点的更多相关文章
- hdu 2857:Mirror and Light(计算几何,点关于直线的对称点,求两线段交点坐标)
Mirror and Light Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU.5692 Snacks ( DFS序 线段树维护最大值 )
HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...
- HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)
HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...
- HDU.1689 Just a Hook (线段树 区间替换 区间总和)
HDU.1689 Just a Hook (线段树 区间替换 区间总和) 题意分析 一开始叶子节点均为1,操作为将[L,R]区间全部替换成C,求总区间[1,N]和 线段树维护区间和 . 建树的时候初始 ...
- R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数
R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- HDU.1556 Color the ball (线段树 区间更新 单点查询)
HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...
- HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)
HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...
- HDU 2857 Mirror and Light
/* hdu 2857 Mirror and Light 计算几何 镜面反射 */ #include<stdio.h> #include<string.h> #include& ...
随机推荐
- 写Java也得了解CPU--CPU缓存
CPU,一般认为写C/C++的才需要了解,写高级语言的(Java/C#/pathon...)并不需要了解那么底层的东西.我一开始也是这么想的,但直到碰到LMAX的Disruptor,以及马丁的博文,才 ...
- int,long,unsigned的值范围
unsigned int 0-4294967295 int 2147483648-2147483647 unsigned long 0-4294967295long 2147483 ...
- C#微信公众号开发系列教程五(接收事件推送与消息排重)
微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...
- K-means算法和矢量量化
语音信号的数字处理课程作业——矢量量化.这里采用了K-means算法,即假设量化种类是已知的,当然也可以采用LBG算法等,不过K-means比较简单.矢量是二维的,可以在平面上清楚的表示出来. 1. ...
- nios II--实验3——led 100M硬件部分
led_100M 硬件开发 新建原理图 参照实验二(led) QSys调用模块 参照实验二(led) 原理图添加IP模块 参照实验二(led),在调用PLL的时候需要修改系统和SDRAM的时钟频率为1 ...
- XMl各种格式转换功能代码
package com.cdv.test; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.File ...
- 实现解耦-Spring.Net
spring.net属于IOC(中文名:控制反转)的思想实现. 概念解释: 控制反转概念: 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来 ...
- ubuntu中安装VMWare tools
在进入VMware Workstation之后找到虚拟机然后选择安装VMWare Tools 在下载的安装包中找到linux.iso,比如我的是C:\Program Files (x86)\VMwar ...
- 天气预报API获取
1.citycode: http://mobile.weather.com.cn/js/citylist.xml http://files.cnblogs.com/files/ys-wuhan/cit ...
- android修改系统时区
动态注册广播接收器必须有实例存在 静态不要实例存在 设置系统时区: AlarmManager mAlarmManager = (AlarmManager)getSystemService(Con ...