Pick-up sticks(判断两条线段是否相交)
| Time Limit: 3000MS | Memory Limit: 65536K | |
| Total Submissions: 8351 | Accepted: 3068 |
Description
Input
Output
The picture to the right below illustrates the first case from input.
Sample Input
5
1 1 4 2
2 3 3 1
1 -2.0 8 4
1 4 8 2
3 3 6 -2.0
3
0 0 1 1
1 0 2 1
2 0 3 1
0
Sample Output
Top sticks: 2, 4, 5.
Top sticks: 1, 2, 3. 题意:给n个木条,每条线段元素包含四个数,分别是其端点的横纵坐标,n个木条依次按先后顺序扔出,问放在最上面的木条的序号; 思路:判断两条线段相交问题,判断每个木条与它后面的木条是否相交,若相交,则当前木条肯定不是最上面的,用标记数组进行标记,最后遍历一遍输出序号就可以了;

#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn = ; struct point
{
double x,y;
point(){}
point(double a,double b):x(a),y(b) {}
friend point operator - (const point &a,const point &b)
{
return point(a.x-b.x,a.y-b.y);
}
friend double operator ^(const point &a,const point &b)
{
return a.x*b.y-a.y*b.x;
}
friend double operator *(const point &a, const point &b)
{
return a.x*b.x + a.y*b.y;
}
}; struct line
{
point a;
point b;
int flag;
line (){}
line (point x, point y):a(x),b(y) {}
}L[maxn]; const double eps = 1e-;
int cmp(double x)
{
if(fabs(x) < eps)
return ;
if(x > )
return ;
return -;
} bool inter(line L1, line L2)//判断两条线段是否相交
{
return
//快速排斥实验
max(L1.a.x,L1.b.x) >= min(L2.a.x,L2.b.x) &&
max(L2.a.x,L2.b.x) >= min(L1.a.x,L1.b.x) &&
max(L1.a.y,L1.b.y) >= min(L2.a.y,L2.b.y) &&
max(L2.a.y,L2.b.y) >= min(L1.a.y,L1.b.y) &&
//跨立实验
cmp((L2.a-L1.a)^(L1.b-L1.a))*cmp((L2.b-L1.a)^(L1.b-L1.a)) <= &&
cmp((L1.a-L2.a)^(L2.b-L2.a))*cmp((L1.b-L2.a)^(L2.b-L2.a)) <= ;
} int main()
{
int n;
while(~scanf("%d",&n) && n)
{
double x1,y1,x2,y2;
struct point p1,p2;
for(int i = ; i < n; i++)
{
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
p1.x = x1;
p1.y = y1;
p2.x = x2;
p2.y = y2;
L[i].a = p1;
L[i].b = p2;
L[i].flag = ;
} for(int i = ; i < n-; i++)
{
for(int j = i+; j < n; j++)
{
if(inter(L[i],L[j]))//如果第i条线段与第j条线段(i<j)相交,第i条线段显然不可能是最上边的;
{
L[i].flag = ;
break;
}
}
} printf("Top sticks:");
int ok = ;
for(int i = ; i < n; i++)
{
if(L[i].flag == )
{
if(ok == )
{
printf(" %d",i+);
ok = ;
}
else printf(", %d",i+);
}
}
printf(".\n"); }
return ;
}
判断两条线段是否相交问题:
(1) 快速排斥试验
设以线段 P1P2 为对角线的矩形为 R , 设以线段 Q1Q2 为对角线的矩形为 T ,如果 R 和 T
不相交,显然两线段不会相交。
(2) 跨立试验
如果两线段相交,则两线段必然相互跨立对方。若 P1P2 跨立 Q1Q2 ,则矢量 ( P1 - Q1 ) 和
( P2 - Q1 ) 位于矢量 ( Q2 - Q1 ) 的两侧,
即 ( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0 。
上式可改写成 ( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0 。
当 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时,说明 ( P1 - Q1 ) 和 ( Q2 - Q1 ) 共线,
但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2 上;
同理, ( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2 上。
所以判断 P1P2 跨立 Q1Q2 的依据是:
( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0 。
同理判断 Q1Q2 跨立 P1P2 的依据是:
( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0 。
当快速排斥实验和跨立实验都满足时,才说明两天线段相交;
Pick-up sticks(判断两条线段是否相交)的更多相关文章
- [CSharpTips]判断两条线段是否相交
判断两条线段是否相交 主要用到了通过向量积的正负判断两个向量位置关系 向量a×向量b(×为向量叉乘),若结果小于0,表示向量b在向量a的顺时针方向:若结果大于0,表示向量b在向量a的逆时针方向:若等于 ...
- c# 判断两条线段是否相交(判断地图多边形是否相交)
private void button1_Click(object sender, EventArgs e) { //var result = intersect3(point1, point2, p ...
- 计算几何--判断两条线段相交--poj 2653
Pick-up sticks Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 8862 Accepted: 3262 De ...
- 求两条线段交点zz
"求线段交点"是一种非常基础的几何计算, 在很多游戏中都会被使用到. 下面我就现学现卖的把最近才学会的一些"求线段交点"的算法说一说, 希望对大家有所帮助. 本 ...
- 平面内,线与线 两条线找交点 两条线段的位置关系(相交)判定与交点求解 C#
个人亲自编写.测试,可以正常使用 道理看原文,这里不多说 网上找到的几篇基本都不能用的 C#代码 bool Equal(float f1, float f2) { return (Math ...
- 两条线段求交点+叉积求面积 poj 1408
题目链接:https://vjudge.net/problem/POJ-1408 题目是叫我们求出所有四边形里最大的那个的面积. 思路:因为这里只给了我们正方形四条边上的点,所以我们要先计算横竖线段两 ...
- The 2015 China Collegiate Programming Contest D.Pick The Sticks hdu 5543
Pick The Sticks Time Limit: 15000/10000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others ...
- 判断线段和直线相交 POJ 3304
// 判断线段和直线相交 POJ 3304 // 思路: // 如果存在一条直线和所有线段相交,那么平移该直线一定可以经过线段上任意两个点,并且和所有线段相交. #include <cstdio ...
- 2015南阳CCPC D - Pick The Sticks dp
D - Pick The Sticks Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description The story happened lon ...
随机推荐
- ios从相册:摄像头中获取视频
ios从相册/摄像头中获取视频 如何从相册中获取视频 使用的是一个和获取照片相同的类UIImagePickerController //相册中获取视频 - (IBAction)clickViedoOF ...
- php mysqli注意问题
今天写了这个一段代码 function ip_get_method($action , $device){ if($action != 'search'){ request_die(false,'un ...
- css考核点整理(十一)-响应式开发经验,响应式页面的三种核心技术是什么
响应式开发经验,响应式页面的三种核心技术是什么
- HTML5表单提交和PHP环境搭建
HTML5表单提交相关内容和PHP环境搭建需要的软件(只备注) (2)举例介绍 (3)PHP环境搭建
- iBatis 的删除一条记录
Student.xml 设置删除参数的类型,可以是一个对象的 <delete id="delStudent" parameterClass="int" & ...
- 手势交互之GestureDetector
GsetureDetector 一.交互过程 触屏的一刹那,触发MotionEvent事件 被OnTouchListener监听,在onTouch()中获得MotionEvent对象 GestureD ...
- sql查询过程中 update,insert,delete可视化收影响行数
insert into test_tb output inserted.id,inserted.data values('c'),('d') delete from test_tb output de ...
- jQuery 效果- 动画
jQuery animate() 方法允许您创建自定义的动画. jQuery 动画实例 jQuery jQuery 动画 - animate() 方法 jQuery animate() 方法用于创建自 ...
- [转]PHP echo, print, printf, sprintf函数的区别和使用
1. echo函数: 输出函数,是命令,不能返回值.echo后面可以跟很多个参数,之间用分号隔开,如: echo $myvar1; echo 1,2,$myvar,"<b>bol ...
- SGU 125.Shtirlits
时间限制:0.25s 空间限制:4M 题意: 有N*N的矩阵(n<=3),对所有i,j<=n有G[i][j]<=9,定义f[i][j]为G[i][j]四周大于它的数的个数(F[i][ ...