zoukankan      html  css  js  c++  java
  • poj2826 An Easy Problem?!(计算几何)

    传送门

    •题意

    两根木块组成一个槽,给定两个木块的两个端点

    雨水竖直下落,问槽里能装多少雨水,

    •思路

    找不能收集到雨水的情况

    我们令线段较高的点为s点,较低的点为e点

    ①两条木块没有交点

    ②平行或重合

    ③至少有一条木块水平(雨水会滑落)

    ④形成覆盖,如"$wedge $","人",还有比较难想的上边长下边短的情况

    •  其中形成"$wedge$"型和"人"型 都是两条线段的交点比两条线段中较低的s点同高,

          也就是不大于较高的s点

    • 上长下短的覆盖是两个s点都大于交点而不能存水的唯一情况

         如上图,我们可以在a.x出从b上引一条竖直线,看是否与a有交点,如果有说明覆盖了

    能收集到雨水的情况要注意 水面与较低的s点水平

    •代码

      1 //#include<bits/stdc++.h>
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 
      8 // `计算几何模板`
      9 const double eps = 1e-12;
     10 const double inf = 1e20;
     11 const double pi = acos(-1.0);
     12 const int maxp = 1010;
     13 //`Compares a double to zero`
     14 int sgn(double x){
     15     if(fabs(x) < eps)return 0;
     16     if(x < 0)return -1;
     17     else return 1;
     18 }
     19 //square of a double
     20 inline double sqr(double x){return x*x;}
     21 /*
     22  * Point
     23  * Point()               - Empty constructor
     24  * Point(double _x,double _y)  - constructor
     25  * input()             - double input
     26  * output()            - %.2f output
     27  * operator ==         - compares x and y
     28  * operator <          - compares first by x, then by y
     29  * operator -          - return new Point after subtracting curresponging x and y
     30  * operator ^          - cross product of 2d Points
     31  * operator *          - dot product
     32  * len()               - gives length from origin
     33  * len2()              - gives square of length from origin
     34  * distance(Point p)   - gives distance from p
     35  * operator + Point b  - returns new Point after adding curresponging x and y
     36  * operator * double k - returns new Point after multiplieing x and y by k
     37  * operator / double k - returns new Point after divideing x and y by k
     38  * rad(Point a,Point b)- returns the angle of Point a and Point b from this Point
     39  * trunc(double r)     - return Point that if truncated the distance from center to r
     40  * rotleft()           - returns 90 degree ccw rotated Point
     41  * rotright()          - returns 90 degree cw rotated Point
     42  * rotate(Point p,double angle) - returns Point after rotateing the Point centering at p by angle radian ccw
     43  */
     44 struct Point{
     45     double x,y;
     46     Point(){}
     47     Point(double _x,double _y){
     48         x = _x;
     49         y = _y;
     50     }
     51     void input(){
     52         scanf("%lf%lf",&x,&y);
     53     }
     54     void output(){
     55         printf("%.2f %.2f
    ",x,y);
     56     }
     57     bool operator == (Point b)const{
     58         return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
     59     }
     60     bool operator < (Point b)const{
     61         return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
     62     }
     63     Point operator -(const Point &b)const{
     64         return Point(x-b.x,y-b.y);
     65     }
     66     //叉积
     67     double operator ^(const Point &b)const{
     68         return x*b.y - y*b.x;
     69     }
     70     //点积
     71     double operator *(const Point &b)const{
     72         return x*b.x + y*b.y;
     73     }
     74     //返回长度
     75     double len(){
     76         return hypot(x,y);//库函数
     77     }
     78     //返回长度的平方
     79     double len2(){
     80         return x*x + y*y;
     81     }
     82     //返回两点的距离
     83     double distance(Point p){
     84         return hypot(x-p.x,y-p.y);
     85     }
     86     Point operator +(const Point &b)const{
     87         return Point(x+b.x,y+b.y);
     88     }
     89     Point operator *(const double &k)const{
     90         return Point(x*k,y*k);
     91     }
     92     Point operator /(const double &k)const{
     93         return Point(x/k,y/k);
     94     }
     95     //`计算pa  和  pb 的夹角`
     96     //`就是求这个点看a,b 所成的夹角`
     97     //`测试 LightOJ1203`
     98     double rad(Point a,Point b){
     99         Point p = *this;
    100         return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
    101     }
    102     //`化为长度为r的向量`
    103     Point trunc(double r){
    104         double l = len();
    105         if(!sgn(l))return *this;
    106         r /= l;
    107         return Point(x*r,y*r);
    108     }
    109     //`逆时针旋转90度`
    110     Point rotleft(){
    111         return Point(-y,x);
    112     }
    113     //`顺时针旋转90度`
    114     Point rotright(){
    115         return Point(y,-x);
    116     }
    117     //`绕着p点逆时针旋转angle`
    118     Point Rotate(Point p,double angle){
    119         Point v = (*this) - p;
    120         double c = cos(angle), s = sin(angle);
    121         return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);
    122     }
    123 };
    124 /*
    125  * Stores two Points
    126  * Line()                         - Empty constructor
    127  * Line(Point _s,Point _e)        - Line through _s and _e
    128  * operator ==                    - checks if two Points are same
    129  * Line(Point p,double angle)     - one end p , another end at angle degree
    130  * Line(double a,double b,double c) - Line of equation ax + by + c = 0
    131  * input()                        - inputs s and e
    132  * adjust()                       - orders in such a way that s < e
    133  * length()                       - distance of se
    134  * angle()                        - return 0 <= angle < pi
    135  * relation(Point p)              - 3 if Point is on line
    136  *                                  1 if Point on the left of line
    137  *                                  2 if Point on the right of line
    138  * Pointonseg(double p)           - return true if Point on segment
    139  * parallel(Line v)               - return true if they are parallel
    140  * segcrossseg(Line v)            - returns 0 if does not intersect
    141  *                                  returns 1 if non-standard intersection
    142  *                                  returns 2 if intersects
    143  * linecrossseg(Line v)           - line and seg
    144  * linecrossline(Line v)          - 0 if parallel
    145  *                                  1 if coincides
    146  *                                  2 if intersects
    147  * crossPoint(Line v)             - returns intersection Point
    148  * disPointtoline(Point p)        - distance from Point p to the line
    149  * disPointtoseg(Point p)         - distance from p to the segment
    150  * dissegtoseg(Line v)            - distance of two segment
    151  * lineprog(Point p)              - returns projected Point p on se line
    152  * symmetryPoint(Point p)         - returns reflection Point of p over se
    153  *
    154  */
    155 struct Line{
    156     Point s,e;
    157     Line(){}
    158     Line(Point _s,Point _e){
    159         s = _s;
    160         e = _e;
    161     }
    162     bool operator ==(Line v){
    163         return (s == v.s)&&(e == v.e);
    164     }
    165     //`根据一个点和倾斜角angle确定直线,0<=angle<pi`
    166     Line(Point p,double angle){
    167         s = p;
    168         if(sgn(angle-pi/2) == 0){
    169             e = (s + Point(0,1));
    170         }
    171         else{
    172             e = (s + Point(1,tan(angle)));
    173         }
    174     }
    175     //ax+by+c=0
    176     Line(double a,double b,double c){
    177         if(sgn(a) == 0){
    178             s = Point(0,-c/b);
    179             e = Point(1,-c/b);
    180         }
    181         else if(sgn(b) == 0){
    182             s = Point(-c/a,0);
    183             e = Point(-c/a,1);
    184         }
    185         else{
    186             s = Point(0,-c/b);
    187             e = Point(1,(-c-a)/b);
    188         }
    189     }
    190     void input(){
    191         s.input();
    192         e.input();
    193     }
    194     //根据x排序
    195     void adjustx(){
    196         if(e < s)swap(s,e);
    197     }
    198     //根据y排序
    199     void adjusty(){
    200         if(e.y>s.y) swap(s,e);
    201     }
    202     //求线段长度
    203     double length(){
    204         return s.distance(e);
    205     }
    206     //`返回直线倾斜角 0<=angle<pi`
    207     double angle(){
    208         double k = atan2(e.y-s.y,e.x-s.x);
    209         if(sgn(k) < 0)k += pi;
    210         if(sgn(k-pi) == 0)k -= pi;
    211         return k;
    212     }
    213     //`点和直线关系`
    214     //`1  在左侧`
    215     //`2  在右侧`
    216     //`3  在直线上`
    217     int relation(Point p){
    218         int c = sgn((p-s)^(e-s));
    219         if(c < 0)return 1;
    220         else if(c > 0)return 2;
    221         else return 3;
    222     }
    223     // 点在线段上的判断
    224     bool Pointonseg(Point p){
    225         return sgn((p-s)^(e-s)) == 0 && sgn((p-s)*(p-e)) <= 0;
    226     }
    227     //`两向量平行(对应直线平行或重合)`
    228     bool parallel(Line v){
    229         return sgn((e-s)^(v.e-v.s)) == 0;
    230     }
    231     //`两线段相交判断`
    232     //`2 规范相交`
    233     //`1 非规范相交`
    234     //`0 不相交`
    235     int segcrossseg(Line v){
    236         int d1 = sgn((e-s)^(v.s-s));
    237         int d2 = sgn((e-s)^(v.e-s));
    238         int d3 = sgn((v.e-v.s)^(s-v.s));
    239         int d4 = sgn((v.e-v.s)^(e-v.s));
    240         if( (d1^d2)==-2 && (d3^d4)==-2 )return 2;
    241         return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
    242             (d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
    243             (d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
    244             (d4==0 && sgn((e-v.s)*(e-v.e))<=0);
    245     }
    246     //`直线和线段相交判断`
    247     //`-*this line   -v seg`
    248     //`2 规范相交`
    249     //`1 非规范相交`
    250     //`0 不相交`
    251     int linecrossseg(Line v){
    252         int d1 = sgn((e-s)^(v.s-s));
    253         int d2 = sgn((e-s)^(v.e-s));
    254         if((d1^d2)==-2) return 2;
    255         return (d1==0||d2==0);
    256     }
    257     //`两直线关系`
    258     //`0 平行`
    259     //`1 重合`
    260     //`2 相交`
    261     int linecrossline(Line v){
    262         if((*this).parallel(v))
    263             return v.relation(s)==3;
    264         return 2;
    265     }
    266     //`求两直线的交点`
    267     //`要保证两直线不平行或重合`
    268     Point crossPoint(Line v){
    269         double a1 = (v.e-v.s)^(s-v.s);
    270         double a2 = (v.e-v.s)^(e-v.s);
    271         return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
    272     }
    273     //点到直线的距离
    274     double disPointtoline(Point p){
    275         return fabs((p-s)^(e-s))/length();
    276     }
    277     //点到线段的距离
    278     double disPointtoseg(Point p){
    279         if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0)
    280             return min(p.distance(s),p.distance(e));
    281         return disPointtoline(p);
    282     }
    283     //`返回线段到线段的距离`
    284     //`前提是两线段不相交,相交距离就是0了`
    285     double dissegtoseg(Line v){
    286         return min(min(disPointtoseg(v.s),disPointtoseg(v.e)),min(v.disPointtoseg(s),v.disPointtoseg(e)));
    287     }
    288     //`返回点p在直线上的投影`
    289     Point lineprog(Point p){
    290         return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
    291     }
    292     //`返回点p关于直线的对称点`
    293     Point symmetryPoint(Point p){
    294         Point q = lineprog(p);
    295         return Point(2*q.x-p.x,2*q.y-p.y);
    296     }
    297     //求线段交点
    298     Point intersection(Line v)
    299     {
    300         double  a1,a2,b1,b2,c1,c2;
    301         a1=s.y-e.y;
    302         a2=v.s.y-v.e.y;
    303         b1=e.x-s.x;
    304         b2=v.e.x-v.s.x;
    305         c1=s.x*e.y-e.x*s.y;
    306         c2=v.s.x*v.e.y-v.e.x*v.s.y;
    307         return Point((c1*b2-c2*b1)/(a2*b1-a1*b2),(c1*a2-c2*a1)/(b2*a1-b1*a2));
    308     }
    309 };
    310 int main()
    311 {
    312     int t;
    313     scanf("%d",&t);
    314     while(t--)
    315     {
    316         double a,b,c,d;
    317         Line l1,l2,l3,l4;
    318         scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
    319         l1=Line(Point(a,b),Point(c,d));
    320         scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
    321         l2=Line(Point(a,b),Point(c,d));
    322         l1.adjusty(),l2.adjusty();
    323 
    324         double s=-1;
    325         if(l1.parallel(l2))///平行或重合
    326             s=0;
    327         else if((!l1.angle())||(!l2.angle()))///k=0
    328             s=0;
    329         else if(l1.segcrossseg(l2)==0)///不相交
    330             s=0;
    331         else if(l1.segcrossseg(l2))///相交
    332         {
    333             Point P=l1.intersection(l2);///获得交点
    334             Point p1,p2;
    335             int flag=0,flag1=0;
    336             if(l1.s.y-P.y>eps) p1=l1.s,flag=1;
    337             if(l2.s.y-P.y>eps) p2=l2.s,flag1=1;
    338             if(flag&&flag1)
    339             {///还有一种情况没有水。上面的y把下面的y覆盖---遮挡判断
    340                 if(p1.y-p2.y>eps)
    341                 {
    342                     if(l1.segcrossseg(Line(p2,Point(p2.x,p1.y+2.0))))
    343                     {
    344                         printf("0.00
    ");
    345                         continue;
    346                     }
    347                 }
    348                 if(p2.y-p1.y>eps)
    349                 {
    350                     if(l2.segcrossseg(Line(p1,Point(p1.x,p2.y+2.0))))
    351                     {
    352                         printf("0.00
    ");
    353                         continue;
    354                     }
    355                 }
    356                 if(p1.y-p2.y>eps)
    357                 {
    358                     ///取p1.x的水平和p2.y,p1与p2.x的交点
    359                     ///水面和低处水平
    360                     double x=p1.x>0?p1.x+1.00:p1.x-1.0;
    361                     p1=l1.intersection(Line(Point(x,p2.y),Point(-x,p2.y)));
    362                 }
    363                 else
    364                 {
    365                     double x=p2.x>0?p2.x+1.00:p2.x-1.0;
    366                     p2=l2.intersection(Line(Point(x,p1.y),Point(-x,p1.y)));
    367                 }
    368                 s=fabs((p1.x-p2.x)*(p1.y-P.y)*0.5)+eps;
    369             }
    370             else
    371                 s=0;
    372         }
    373         printf("%.2f
    ",s);
    374     }
    375 }
    View Code
  • 相关阅读:
    MaskRCNN模型解读
    Centos7下WebLogic安装部署
    CentOS 7 安装 JAVA环境(JDK 1.8)
    Linux下如何查看tomcat是否安装、启动、文件路径、进程ID
    Nacos enable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
    多线程系列(三)之线程池
    多线程系列(二)之Thread类
    多线程系列(一)之多线程基础
    Vue2/Vue3 自定义组件库
    EF Core使用单独的项目管理迁移
  • 原文地址:https://www.cnblogs.com/MMMinoz/p/11492764.html
Copyright © 2011-2022 走看看