zoukankan      html  css  js  c++  java
  • poj 3304 Segments 直线 线段求交

    在二维空间上,给定一组线段,能否存在这样的一条直线,使所有线段在这条直线的投影会在一个点上。
    如果沿着这个投影点做直线的垂线,那么这条垂线必会与所有的线段相交。那么本题就转换为能否找到一条直线与所有的线段相交。
    想找这样的直线,就要去离散化的枚举,本题怎样有效的枚举是关键。
    首先假设有一条直线与所有的线段相交,慢慢平移这条直线,使它恰好在某条线段L1的端点上。当然这个时候直线还是与所有的线段相交。
    然后让直线在这个端点上慢慢旋转,使到直线又经过线段L2的端点。L2和L1要满足不是同一条线段,就算相同,你仍可以继续旋转,总会让直线找到L2,且不与L1同一样的线段。
    这样只要枚举两条线段的端点做直线,判断其它的线段是否与这条直线相交即可。枚举过程中要注意所选的两条线段的端点有可能会在同一个端点上。
     
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #define eps 1e-10
    int n;
    struct point
    {
            double x;
            double y;
    };
    struct line
    {
            point a,b;
    }p[105];
    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);
    }
    double dis(point p1,point p2)
    {
            return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
    }
    bool judge(int i,int j,point p1,point p2)
    {
         int k;
         for(k=0;k<n;k++)
         {
              if(k==i||k==j)
                   continue;
              if(xmult(p1,p[k].a,p2)*xmult(p1,p[k].b,p2)>eps||dis(p1,p2)<eps)
                   return false;
         }
         return true;
    }
    int main()
    {
            int cas,i,j;
            bool flag;
            scanf("%d",&cas);
            while(cas--)
            {
                    scanf("%d",&n);
                    for(i=0;i<n;i++)
                            scanf("%lf%lf%lf%lf",&p[i].a.x,&p[i].a.y,&p[i].b.x,&p[i].b.y);
                    flag=true;
                    for(i=0;i<n-1;i++)
                    {
                            for(j=i+1;j<n;j++)
                            {
                                 flag=false;
                                 if(judge(i,j,p[i].a,p[j].a)||judge(i,j,p[i].a,p[j].b)||judge(i,j,p[i].b,p[j].a)||judge(i,j,p[i].b,p[j].b))
                                 flag=true;
                                 if(flag)
                                      break;
                            }
                            if(flag)
                                 break;
                    }
                    if(flag)
                            printf("Yes!\n");
                    else
                            printf("No!\n");
            }
            system("pause");
            return 0;
    }
  • 相关阅读:
    【数学】三分法
    【数学】【背包】【NOIP2018】P5020 货币系统
    【数学】【CF27E】 Number With The Given Amount Of Divisors
    【单调队列】【P3957】 跳房子
    【极值问题】【CF33C】 Wonderful Randomized Sum
    【DP】【CF31E】 TV Game
    【神仙题】【CF28D】 Don't fear, DravDe is kind
    【线段树】【CF19D】 Points
    【字符串】KMP字符串匹配
    【二维树状数组】【CF10D】 LCIS
  • 原文地址:https://www.cnblogs.com/zxj015/p/2740232.html
Copyright © 2011-2022 走看看