• hdu3712 Detector Placement


    题意:给一束激光,一个三棱柱,三棱柱会折射光,问这束激光最终是否会和y = 0相交;

    分析:模拟题,为了方便处理折射角,事先求出每条边的向内和向外的法向量;

    findpoint : 找第一交点

    step1:  判断激光是否和三角形有规范相交;

    step2: 第一次折射;

    step3:第二次折射,可能无法折射;

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 const int N = 100+10;
     10 const double eps = 1e-8;
     11 const double pi = acos(-1.0);
     12 inline int dcmp(double x) {
     13     return x < -eps ? -1 : x > eps;
     14 }
     15 inline double sqr(double x) {
     16     return x * x;
     17 }
     18 
     19 struct Point{
     20     double x,y;
     21     Point(){}
     22     Point(double _x,double _y):x(_x),y(_y){}
     23     bool operator == (const Point &p) const{
     24         return dcmp(x - p.x) == 0 && dcmp(y - p.y) == 0;
     25     }
     26     Point operator + (const Point &p) const{
     27         return Point(x + p.x, y + p.y);
     28     }
     29     Point operator - (const Point &p) const{
     30         return Point (x - p.x, y - p.y);
     31     }
     32     Point operator * (const double &k) const{
     33         return Point (x * k, y * k);
     34     }
     35     Point operator / (const double &k) const{
     36         return Point (x / k, y / k);
     37     }
     38     double operator * (const Point &p) const{
     39         return x * p.y - y * p.x;
     40     }
     41     double operator / (const Point &p) const{
     42         return x * p.x + y * p.y;
     43     }
     44     double len2() {
     45         return x * x + y * y;
     46     }
     47     double len() {
     48         return sqrt(len2());
     49     }
     50     Point scale(const double &k) {
     51         return dcmp( len() ) ? (*this) * (k / len()) : (*this);
     52     }
     53     Point turnLeft() {
     54         return Point(-y,x);
     55     }
     56     Point turnRight(){
     57         return Point(y,-x);
     58     }
     59     double Distance(const Point &p) {
     60         return sqrt(sqr(x - p.x) + sqr(y - p.y));
     61     }
     62     Point rotate(const Point &p,double angle, double k = 1) {
     63         Point vec = (*this) - p;
     64         double c = cos(angle * k)  , s =sin(angle * k) ;
     65         return p + Point(vec.x * c - vec.y * s, vec.x * s + vec.y * c);
     66     }
     67     void input(){
     68         scanf("%lf%lf",&x,&y);
     69     }
     70     void ot() {
     71         printf("%.3lf %.3lf
    ",x,y);
     72     }
     73 };
     74 double Angle(Point a,Point b) {
     75     return (a/b) / a.len() / b.len();
     76 }
     77 struct Line{
     78     Point a,b;
     79     Line(){}
     80     Line(Point a,Point b):a(a),b(b){}
     81     double operator * (const Point &p) const{
     82         return (b - a) * (p - a);
     83     }
     84     double operator / (const Point &p) const{
     85         return (p - a) / (p - b);
     86     }
     87     bool IsPointOnSeg(const Point &p) {
     88         return dcmp( (a - p) * (b - p) ) == 0 && dcmp( (p - a) / (p - b) ) <= 0;
     89     }
     90     int LineCrossSeg(const Line &v) {//2jiao, 1 dian ,0 wu
     91         int d1 = dcmp( (*this) * v.a), d2 = dcmp((*this) * v.b);
     92         if ((d1 ^ d2) == -2) return 2;
     93         return (d1 == 0 || d2 == 0);
     94     }
     95     Point CrossPoint(const Line &v) {
     96         double s1 = v * a, s2 = v * b;
     97         return ( a * s2 - b * s1 ) / (s2 - s1);
     98     }
     99 };
    100 Line li[3];
    101 int d[3];
    102 Point a[3],b[3],c[3];
    103 Point st,en;
    104 
    105 double u;
    106 int check(int i) {
    107     if (dcmp( (li[i].b - li[i].a) * (a[d[i]] - li[i].a) ) > 0) {
    108         return 1;
    109     }
    110     return 0;
    111 }
    112 void init(){
    113     for (int i = 0; i < 3; i++) {
    114         if (check(i)) {
    115             b[i] = (li[i].b - li[i].a).turnLeft();
    116             c[i] = (li[i].b - li[i].a).turnRight();
    117         }else {
    118             b[i] = (li[i].b - li[i].a).turnRight();
    119             c[i] = (li[i].b - li[i].a).turnLeft();
    120         }
    121     }
    122 }
    123 int ond(Point a,Point b,Point p) {
    124     if (dcmp((p - a) / (b - a)) >= 0) return 1;
    125     return 0;
    126 }
    127 int step1() {
    128     int fg = 0;
    129     Line line = Line(st,en);
    130     for (int i = 0; i < 3; i++) {
    131         if (line.LineCrossSeg(li[i]) == 2) {
    132             Point p = line.CrossPoint(li[i]);
    133             if (ond(st,en,p)) fg = 1;
    134         }
    135     }
    136     if (fg == 0) {
    137 
    138         Point p = line.CrossPoint(Line(Point(0,0),Point(1,0)));
    139         if (ond(st,en,p)) printf("%.3lf
    ",p.x+eps);
    140         else printf("Error
    ");
    141         return 0;
    142     }
    143     return 1;
    144 
    145 }
    146 void findPoint(Point &p,int &id) {
    147     Line line = Line(st,en);
    148     double dis = 1e50;
    149     for (int i = 0; i < 3; i++) {
    150         if (line.LineCrossSeg(li[i])) {
    151             Point tp = line.CrossPoint(li[i]);
    152             if (!ond(st,en,tp)) continue;
    153             double tdis = tp.Distance(st);
    154             if (tdis < dis && dcmp(tdis) != 0) {
    155                 dis = tdis;
    156                 p = tp;
    157                 id = i;
    158             }
    159         }
    160     }
    161 }
    162 void step2() {
    163     Point p;
    164     int id = -1;
    165     findPoint(p,id);
    166     Point vec = en - st;
    167     double cs = Angle(vec,b[id]);
    168     double sn1 = sqrt(1 - cs * cs);
    169     double sn2 = sn1 / u;
    170     double ag = asin(sn1) - asin(sn2);
    171     if (dcmp(vec * b[id]) <= 0) {
    172         vec = (p + vec).rotate(p,-ag);
    173     }else vec = (p + vec).rotate(p,ag);
    174     st = p; en = vec;
    175 }
    176 void step3() {
    177     Point p;
    178     int id = -1;
    179     findPoint(p,id);
    180     Point vec = en - st;
    181     double cs = Angle(vec,c[id]);
    182     double sn1 = sqrt(1 - cs * cs);
    183     double sn2 = sn1 * u;
    184     if (sn2 > 1) {
    185         if (dcmp(p.y) == 0) printf("%.3lf
    ",p.x+eps);
    186         else printf("Error
    ");
    187         return;
    188     }
    189     double ag = asin(sn2) - asin(sn1);
    190     if (dcmp(vec * c[id]) >= 0) {
    191         vec = (p + vec).rotate(p,-ag);
    192     }else vec = (p + vec).rotate(p,ag);
    193     st = p; en = vec;
    194     Point an = Line(st,en).CrossPoint(Line(Point(0,0),Point(1,0)));
    195     if (ond(st,en,an)) {
    196         printf("%.3lf
    ",an.x+eps);
    197     }else printf("Error
    ");
    198 }
    199 void solve(){
    200     init();
    201     if (!step1()) return;
    202     step2();
    203     step3();
    204 }
    205 int main(){
    206    // cout<<Line(Point(0,0),Point(1,0)).LineCrossSeg(Line(Point(0,0),Point(1,0)))<<endl;
    207     int T; scanf("%d",&T);
    208     while (T--) {
    209         st.input(); en.input();
    210         for (int i = 0; i < 3; i++) a[i].input();
    211         li[0] = Line(a[0],a[1]); d[0] = 2;
    212         li[1] = Line(a[1],a[2]); d[1] = 0;
    213         li[2] = Line(a[2],a[0]); d[2] = 1;
    214         scanf("%lf",&u);
    215         solve();
    216     }
    217     return 0;
    218 }
    219 /*
    220 3
    221 0 10
    222 0 20
    223 -1 3 1 2 -1 1
    224 1.325
    225 0 10
    226 0 0
    227 -1 3 1 2 -1 1
    228 1.325
    229 
    230 0 10 0 9
    231 0 0 0 1 1 0
    232 1.0
    233 */
    View Code
  • 相关阅读:
    java泛型介绍
    JavaWeb---总结(十九)Session机制
    ServiceWorker入门介绍一
    Ehcache入门介绍一
    Hadoop入门介绍一
    给安卓端调用的短信发送接口demo
    Java开发需要注意的流程
    一些题
    省选模拟3
    省选模拟2
  • 原文地址:https://www.cnblogs.com/Rlemon/p/3398254.html
Copyright © 2020-2023  润新知