poj 3304 Segments(解题报告)
收获:举一反三:刷一道会一道
1:思路转化:(看的kuangbin的思路)
首先是在二维平面中:如果有很多线段能够映射到这个直线上并且至少重合于一点,充要条件: 是过这个点的此条直线的垂线与其他所有直线都相交
取极限情况: 此垂线与直线的交点是端点的情况
则可以通过枚举所有的端点所在的直线进行判断,若不存在这样的直线,则输出No!
细节:枚举的两端点存在重合的情况
为了谨慎起见:枚举所有可能情况,包括输入的线段所在的直线也是垂线的情况
2:直线与线段相交和线段与线段相交的区别:
线段的端点是不可变的,而对于线段所在的直线
bool line_segment(Line l1,Line l2)//l1直线和l2线段相交判断(写反了就会错)
{
return cmp(det(l2.s,l1.s,l1.e))*cmp(det(l2.e,ll.s,l1.e))<=0;
} bool segmen_segment(Line l1,Line l2)//线段l1和线段l2
{
return (cmp(det(l2.s,l1.s,l1.e))*cmp(det(l2.e,l1.s,l1.e))<=0)&&(cmp(det(l1.s,l2.s,l2.e))*cmp(det(l1.e,l2.s,l2.e))<=0);
}
如下图:(此处只讨论严格相交,严格相交:两条线段只有一个公共点,而且这个公共点不是端点)
#include<iostream>
#include<cmath>
//完全参考kuangbin的代码
using namespace std;
const double eps = 1e-8; int sgn(double x)
{
if(fabs(x)<eps)return 0;
if(x<0)return -1;
return 1;
} struct Point
{
double x,y;
Point(){};
Point (double _x,double _y)
{x=_x;y=_y;}
Point operator - (const Point &b)const
{
return Point(x-b.x,y-b.y);
}
double operator *(const Point &b)const
{
return x*b.x+y*b.y;
}
double operator ^ (const Point &b)const
{
return x*b.y-y*b.x;
}
}; struct Line{
Point s,e;
Line() {}
Line (Point _s,Point _e)
{
s=_s;
e=_e;
}
}; const int MAXN=1010;
Line line[MAXN]; double xmult(Point p0,Point p1,Point p2)//叉积
{
return (p1-p0)^(p2-p0);
} bool xmultline(Line l1,Line l2)//判断直线1和线段l2是否相交
{
//return sgn(xmult(l2.e,l1.e,l1.s))*sgn(xmult(l2.s,l1.e,l1.s))<=0;
return sgn(xmult (l1.e,l2.e,l2.s))*sgn(xmult(l1.s,l2.e,l2.s))<=0;//错误
} double dis(Point p1,Point p2)
{
return sqrt((p1-p2)*(p1-p2));
}
bool check(Line ll,int n)
{
if(sgn(dis(ll.s,ll.e))==0)return false ; for(int i=0;i<n;i++)
{
if(xmultline(ll,line[i])==false)
return false;
}
return true;
} int main ()
{
int t;
cin>>t;
while(t--)
{
int m;
cin>>m;
double x1,x2,y1,y2;
for(int i=0;i<m;i++)
{
cin>>x1>>y1>>x2>>y2;
line[i]=Line(Point(x1,y1),Point(x2,y2));
}
bool flag= false;
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
{
int n=m;
if(check(Line(line[i].s,line[j].s),n) || check(Line(line[i].s,line[j].e),n)
|| check(Line(line[i].e,line[j].s),n) || check(Line(line[i].e,line[j].e),n) )
{
flag=true;
break;
}
}
if(flag)
cout<<"Yes!"<<endl;
else
cout<<"No!"<<endl;
}
return 0;
}
自己照着套路写的:
#include<iostream>
#include<cmath> using namespace std; double eps=1e-8; int cmp(double x)
{
if(fabs(x)<=eps)return 0;
if(x<0)return -1;
return 1;
} struct Point{
double x,y;
Point (){}
Point (double _x,double _y)
{
x=_x,y=_y;
}
Point operator -(const Point &b)const
{
return Point (x-b.x,y-b.y);
}
double operator *(const Point &b)const
{
return x*b.x+y*b.y;
}
double operator ^(const Point &b)const
{
return x*b.y-y*b.x;
}
bool operator ==(const Point &b)const//重载==
{
if(cmp(fabs(x-b.x))==0&&cmp(fabs(y-b.y)==0))
return true;
return false;
}
}; struct Line{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s=_s;
e=_e;
}
}; const int MAXN =110;
Line line[MAXN];
double xmult(Point p0,Point p1,Point p2)
{
return (p1-p0)^(p2-p0);
} bool line_segment(Line l1,Line l2 )//直线l1和线段l2
{
if(cmp(xmult(l2.s,l1.s,l1.e))*cmp(xmult(l2.e,l1.s,l1.e))<=0)
return true;
return false;
}
bool chack(Line ll ,int m)//与所有边相交判断
{
if(ll.s==ll.e)return false ;
for(int i=0;i<m;i++)
{
if(line_segment(ll,line[i])==false)
return false;
}
return true;
} int main ()
{
int t;
cin>>t;
int n;
double x1,x2,y1,y2;
while(t--)
{
cin>>n;
for(int i=0;i<n;i++)
{ cin>>x1>>y1>>x2>>y2;
line[i]=Line(Point(x1,y1),Point(x2,y2));
}
bool flag=false;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
int m=n;
if(chack(Line(line[i].s,line[j].s),m)||chack(Line(line[i].s,line[j].e),m)||chack(Line(line[i].e,line[j].s),m)||chack(Line(line[i].e,line[j].e),m))
flag=true;
}
if(flag)
cout<<"Yes!"<<endl;
else
cout<<"No!"<<endl; } return 0;
}
poj 3304 Segments(解题报告)的更多相关文章
- POJ 3304 Segments(判断直线与线段是否相交)
题目传送门:POJ 3304 Segments Description Given n segments in the two dimensional space, write a program, ...
- POJ 3304 Segments(计算几何:直线与线段相交)
POJ 3304 Segments 大意:给你一些线段,找出一条直线可以穿过全部的线段,相交包含端点. 思路:遍历全部的端点,取两个点形成直线,推断直线是否与全部线段相交,假设存在这种直线,输出Yes ...
- POJ 3304 Segments 判断直线和线段相交
POJ 3304 Segments 题意:给定n(n<=100)条线段,问你是否存在这样的一条直线,使得所有线段投影下去后,至少都有一个交点. 思路:对于投影在所求直线上面的相交阴影,我们可以 ...
- POJ 2002 Squares 解题报告(哈希 开放寻址 & 链式)
经典好题. 题意是要我们找出所有的正方形.1000点,只有枚举咯. 如图,如果我们知道了正方形A,B的坐标,便可以推测出C,D两点的坐标.反之,遍历所有点作为A,B点,看C,D点是否存在.存在的话正方 ...
- POJ 3304 Segments (判断直线与线段相交)
题目链接:POJ 3304 Problem Description Given n segments in the two dimensional space, write a program, wh ...
- 简单几何(线段与直线的位置) POJ 3304 Segments
题目传送门 题意:有若干线段,问是否存在一条直线,所有线段投影到直线上时至少有一个公共点 分析:有一个很好的解题报告:二维平面上线段与直线位置关系的判定.首先原问题可以转换为是否存在一条直线与所有线段 ...
- POJ 3304 Segments 基础线段交判断
LINK 题意:询问是否存在直线,使得所有线段在其上的投影拥有公共点 思路:如果投影拥有公共区域,那么从投影的公共区域作垂线,显然能够与所有线段相交,那么题目转换为询问是否存在直线与所有线段相交.判断 ...
- POJ 3304 Segments (直线和线段相交判断)
Segments Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7739 Accepted: 2316 Descript ...
- 【原创】poj ----- 1182 食物链 解题报告
题目地址: http://poj.org/problem?id=1182 题目内容: 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submi ...
随机推荐
- go mod 拉取私有仓库
前言 如果代码中依赖了本地的包, 这个包是托管在内网 Gitlab 中, 而且不是 HTTPS 服务,那么应该怎样使用 go mod 拉取代码呢? 本文会给你我的答案 正文 首先我们要知道, 如果本地 ...
- 十八:SQL注入之堆叠及绕WAF
堆叠查询注入 (双查询注入) stacked injections(堆叠注入)从名词的含义就可以看到是一堆的SQL语句一起执行,而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一 ...
- VmwareTools显示灰色无法安装
VMware不安装VMware Tools无法全屏,然后实机之间不能传输文件等. 安装Vmware Tools显示是灰色的,详细解决方案如下 打开虚拟机设置,CD/DVD 选择ISO映像文件 在Vmw ...
- Java 多线程读取文件并统计词频 实例 出神入化的《ThreadPoolExecutor》
重在展示多线程ThreadPoolExecutor的使用,和线程同步器CountDownLatch,以及相关CAS的原子操作和线程安全的Map/队列. ThreadPool主线程 1 import j ...
- Ice系列--傻瓜式服务开发IceBox
前言 相信大家在没有接触过框架之前,都自己或多或少的开发过一些应用服务.每个应用服务除了业务配置还有很多环境配置,资源配置等,这些跟部署相关的配置.服务跟配置文件是一种静态绑定的方式,更新配置还需要重 ...
- 转 11 jmeter之图形监控扩展
11 jmeter之图形监控扩展 Jmeter默认监听器的缺陷 Jmeter默认的监听器在表格.文字方面比较健全,但是在图形监控方面比较逊色,尤其在监控Windows或Linux的系统资源方面.但 ...
- 《UML与设计原则》--第四小组
关于设计模式与原则 一.设计模式简介 设计模式描述了软件设计过程中某一类常见问题的一般性的解决方案.而面向对象设计模式描述了面向对象设计过程中特定场景下.类与相互通信的对象之间常见的组织关系. 二.G ...
- vfd-cloud——一个适合练习上手的云存储网盘springboot项目(开发中)
vfd-cloud 一个基于SpringBoot的云存储网盘项目,适合练手学习SpringBoot,用到的技术栈列到了下面.支持用户的注册登陆及修改密码,利用邮箱进行验证.支持 ...
- HA工作机制
HA工作机制 HA:高可用(7*24小时不中断服务) 主要的HA是针对集群的master节点的,即namenode和resourcemanager,毕竟DataNode挂掉之后影响 不是特别大,重启就 ...
- (012)每日SQL学习:TO_CHAR(DATE,FORMAT)
SYSDATE 2009-6-16 15:25:10 TRUNC(SYSDATE) 2009-6-16 TO_CHAR(SYSDATE,'YYYYMMDD') 20090616 到日 TO_CHAR( ...