HDU 2857 Mirror and Light (点关于线的对称点)

Mirror and Light

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 962    Accepted Submission(s): 436

Problem Description
The light travels in a straight line and always goes in the minimal path between two points, are the basic laws of optics.

Now, our problem is that, if a branch of light goes into a large and infinite mirror, of course,it will reflect, and leave away the mirror in another direction. Giving you the position of mirror and the two points the light goes in before and after the reflection, calculate the reflection point of the light on the mirror.
  
You can assume the mirror is a straight line and the given two points can’t be on the different sizes of the mirror.
 

Input
The first line is the number of test case t(t<=100).
  
The following every four lines are as follow:
  X1 Y1
  X2 Y2
  Xs Ys
  Xe Ye

  (X1,Y1),(X2,Y2) mean the different points on the mirror, and (Xs,Ys) means the point the light travel in before the reflection, and (Xe,Ye) is the point the light go after the reflection.

  The eight real number all are rounded to three digits after the decimal point, and the absolute values are no larger than 10000.0.
 

Output
  Each lines have two real number, rounded to three digits after the decimal point, representing the position of the reflection point.
 

Sample Input
1 0.000 0.000 4.000 0.000 1.000 1.000 3.000 1.000
 

Sample Output
2.000 0.000
 

Source

题意:给你镜子的位置(用两点确定的一条直线表示),光源,光的反射点,求光在镜子的折射点。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <cmath>
#include <map>
using namespace std;
const int N = 10005;
const double INF  = 1E200;
const double EP  = 1E-8;
const double PI  = acos(-1.0);
int sgn(double x)
{
    if(fabs(x) < EP)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct POINT
{
    double x;
    double y;
    POINT(double a=0double b=0)
    {
        x=a;    //constructor
        y=b;
    }
    void input()
    {
        scanf("%lf%lf", &x, &y);
    }
};
struct LINE      // 直线的解析方程 a*x+b*y+c=0  为统一表示,约定 a >= 0
{
    double a;
    double b;
    double c;
    LINE(double d1=1double d2=-1double d3=0)
    {
        a=d1;
        b=d2;
        c=d3;
    }
};
// 根据已知两点坐标,求过这两点的直线解析方程: a*x+b*y+c = 0  (a >= 0)
LINE makeline(POINT p1,POINT p2)
{
    LINE tl;
    int sign = 1;
    tl.a=p2.y-p1.y;
    if(tl.a<0)
    {
        sign = -1;
        tl.a=sign*tl.a;
    }
    tl.b=sign*(p1.x-p2.x);
    tl.c=sign*(p1.y*p2.x-p1.x*p2.y);
    return tl;
}
// 求点p关于直线l的对称点
POINT symmetry(LINE l,POINT p)
{
    POINT tp;
    tp.x=((l.b*l.b-l.a*l.a)*p.x-2*l.a*l.b*p.y-2*l.a*l.c)/(l.a*l.a+l.b*l.b);
    tp.y=((l.a*l.a-l.b*l.b)*p.y-2*l.a*l.b*p.x-2*l.b*l.c)/(l.a*l.a+l.b*l.b);
    return tp;
}
POINT intersection(POINT u1,POINT u2,POINT v1,POINT v2)
{
    POINT ret=u1;
    double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
             /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
    ret.x+=(u2.x-u1.x)*t;
    ret.y+=(u2.y-u1.y)*t;
    return ret;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        POINT z1,z2,s,e;
        z1.input();
        z2.input();
        s.input();
        e.input();
        LINE z = makeline(z1,z2);
        POINT dui = symmetry(z,s);
        POINT ans = intersection(z1,z2,dui,e);
        printf("%.3f %.3f\n",ans.x,ans.y);
    }
    return 0;
}
View Code

 

posted @ 2015-08-03 13:29  Doli  阅读(150)  评论(0编辑  收藏  举报