ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2984. 线段

2022-09-12 21:00:31  阅读:153  来源: 互联网

标签:直线 int 线段 所有 2984 端点 define


题意

在二维平面内有 n 条线段,请你编写一个程序,判断是否存在一条直线满足将这 n 条线段投影到该直线上后,所有的投影线段至少具有一个公共点。

思路

转化题意
我们发现如果可以找到一个直线与所有的线段都相交;
那么所有的线段的投影一定都交于这个直线与其垂线的垂足处。

那么问题就转化为如何找一个可以穿过所有线段的直线?

我们肯定不能暴力找所有的坐标判断是否相交。这里我们使用一个计算几何常用的技巧:旋转直线。

我们可以先找一个过一个线段的直线,然后我们旋转他。
我们把这个直线的定点定为这个线段的端点,然后旋转。因为我们要满足能够与其他的线段相交,所以我们旋转的时候有一个限制,就是不能超过另一个线段的一个端点,所以我们可以把所有的候选直线限定到所有线段的端点的连线的直线。

所以我们可以\(O(n^2)\),枚举所有线段的端点,然后 \(O(n)\) 暴力判断是否都与其他的线段有交点,如果存在一个直线与所有的线段有交点说明一定存在解,输出 Yes!。

那么现在的问题转化为我们如何判断一个线段和一个直线是否有交点
判断线段的两个端点是否在直线的异侧即可。

代码


#include<bits/stdc++.h>
#define int long long
#define pdd pair<double,double> 
#define x first
#define y second
using namespace std;
const int N = 210;
const double eps=1e-8;

int n;
pdd a[N],b[N],q[N];

int sign(double x){
  if(abs(x)<eps) return 0;
  if(x<0) return -1;
  else return 1;
}
int cmp(double x,double y){
  if(abs(x-y)<eps) return 0;
  if(x<y) return -1;
  else return 1;
}
double cross(double x1,double y1,double x2,double y2){
  return x1*y2-x2*y1;
}
double area(pdd a,pdd b,pdd c){
  return cross(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
bool check(){
  for(int i=0;i<n*2;i++)
    for(int j=i+1;j<n*2;j++){
      if(!cmp(q[i].x,q[j].x) && !cmp(q[i].y,q[j].y)) continue;
      bool flag=true;
      for(int k=0;k<n;k++){
        if(sign(area(q[i],q[j],a[k])) * sign(area(q[i],q[j],b[k]))>0)
        {
          flag=false;
          break;
        }
      }
      if(flag) return true;
    }
return false;    
}
void solve(){
  cin>>n;
  for(int i=0,k=0;i<n;i++) {
    double x1,y1,x2,y2;
    cin>>x1>>y1>>x2>>y2;
     q[k++]={x1, y1}, q[k++]={x2, y2};
    a[i]={x1,y1},b[i]={x2,y2};
  }
 

  if(check()) puts("Yes!");
  else puts("No!");
} 

signed main(){
  int t=1;
  cin>>t;
  while(t--)
  solve();
  return 0;
}

原文:
作者:繁凡さん
链接:https://www.acwing.com/solution/content/26937/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签:直线,int,线段,所有,2984,端点,define
来源: https://www.cnblogs.com/kingwz/p/16687166.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有