zoukankan      html  css  js  c++  java
  • POJ 2653 Pick-up sticks <<判断线段交

    题意

    求与上方的线段都没有交集的线段

    思路

    暴力判断线段交即可。

    判断线段交的方法:

    1.快速排斥实验

    如图,如果两条线段不相交,他们所组成的矩形也不相交,而判断矩形相交是很方便的,用这个方法可以快速筛掉一些线段。

    当然这并不是充要条件,两矩形相交也可能线段不相交。

    所以矩形不相交是线段不相交的充分非必要条件。

    2.那么正常的判断线段交方法:向量叉积,也就是跨立实验

    线段相交,也就是说线段$P_1P_2$跨过了线段$Q_1Q_2$,同样,$Q_1Q_2$跨过了$P_1P_2$,所以有$(overrightarrow{P_1P_2} imesoverrightarrow{P_1Q_1})cdot (overrightarrow{P_1P_2} imesoverrightarrow{P_1Q_2})<=0$使得$Q_1Q_2$跨过了$P_1P_2$

    同理,有$(overrightarrow{Q_1Q_2} imesoverrightarrow{Q_1P_1})cdot (overrightarrow{Q_1Q_2} imesoverrightarrow{Q_1P_2})<=0$使得$P_1P_2$跨过了$Q_1Q_2$

    代码

     1 #include<algorithm>
     2 #include<cstdio>
     3 using namespace std;
     4 const int maxn=1e5+7;
     5 const double eps=1e-8;
     6 struct Point{
     7     double x,y;
     8 };
     9 struct Segment{
    10     Point a,b;
    11 }seg[maxn];
    12 double cross(Point p,Point a,Point b)
    13 {
    14     //cout<<p.x<<","<<p.y<<";"<<a.x<<","<<a.y<<";"<<b.x<<","<<b.y<<endl;
    15     Point pa={a.x-p.x,a.y-p.y};
    16     Point pb={b.x-p.x,b.y-p.y};
    17     double ret=pa.x*pb.y-pa.y*pb.x;
    18     //cout<<ret<<endl;
    19     return ret;
    20 }
    21 bool intersect(Segment l1,Segment l2)
    22 {
    23     return 
    24         max(l1.a.x,l1.b.x) >= min(l2.a.x,l2.b.x) &&
    25         max(l2.a.x,l2.b.x) >= min(l1.a.x,l1.b.x) &&
    26         max(l1.a.y,l1.b.y) >= min(l2.a.y,l2.b.y) &&
    27         max(l2.a.y,l2.b.y) >= min(l1.a.y,l1.b.y) &&
    28         cross(l1.a,l2.a,l1.b)*cross(l1.a,l2.b,l1.b) <= 0 &&
    29         cross(l2.a,l1.a,l2.b)*cross(l2.a,l1.b,l2.b) <= 0;
    30 }
    31 int main()
    32 {
    33     int n;
    34     while(~scanf("%d",&n)&&n)
    35     {
    36         for(int i=0;i<n;i++)
    37         {
    38             scanf("%lf%lf%lf%lf",&seg[i].a.x,&seg[i].a.y,&seg[i].b.x,&seg[i].b.y);
    39         }
    40         printf("Top sticks:");
    41         for(int i=0;i<n-1;i++)
    42         {
    43             for(int j=i+1;j<n;j++)
    44             {
    45                 if(intersect(seg[i],seg[j]))
    46                     goto next;
    47             }
    48             printf(" %d,",i+1);
    49             next:;
    50         }
    51         printf(" %d.
    ",n);
    52 
    53     }
    54 }
  • 相关阅读:
    06-按钮Button
    05-文本视图TextView
    02-运行配置AndroidManifest.xml
    01-编译配置文件build.gradle详解
    jquery获取焦点和失去焦点
    Liunx下安装Oracle11g时Oracle Grid安装包下载向导
    配置虚拟机上的RedHat6 Linux系统的网络(选择的是仅主机模式)
    Redhat镜像-RHEL-官方镜像下载大全
    在VMware中创建一个新的虚拟机 ,安装Linux4.X系统 ,之后在此基础上安装openfiler(网络存储管理实用程序)
    Oracle18C安装后首次创建数据库并用sql developer 创建连接和用户
  • 原文地址:https://www.cnblogs.com/computer-luo/p/10081794.html
Copyright © 2011-2022 走看看