Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 8351 Accepted: 3068

Description

Stan has n sticks of various length. He throws them one at a time on the floor in a random way. After finishing throwing, Stan tries to find the top sticks, that is these sticks such that there is no stick on top of them. Stan has noticed that the last thrown stick is always on top but he wants to know all the sticks that are on top. Stan sticks are very, very thin such that their thickness can be neglected.

Input

Input consists of a number of cases. The data for each case start with 1 <= n <= 100000, the number of sticks for this case. The following n lines contain four numbers each, these numbers are the planar coordinates of the endpoints of one stick. The sticks are listed in the order in which Stan has thrown them. You may assume that there are no more than 1000 top sticks. The input is ended by the case with n=0. This case should not be processed.

Output

For each input case, print one line of output listing the top sticks in the format given in the sample. The top sticks should be listed in order in which they were thrown.

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(判断两条线段是否相交)的更多相关文章

  1. [CSharpTips]判断两条线段是否相交

    判断两条线段是否相交 主要用到了通过向量积的正负判断两个向量位置关系 向量a×向量b(×为向量叉乘),若结果小于0,表示向量b在向量a的顺时针方向:若结果大于0,表示向量b在向量a的逆时针方向:若等于 ...

  2. c# 判断两条线段是否相交(判断地图多边形是否相交)

    private void button1_Click(object sender, EventArgs e) { //var result = intersect3(point1, point2, p ...

  3. 计算几何--判断两条线段相交--poj 2653

    Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8862   Accepted: 3262 De ...

  4. 求两条线段交点zz

    "求线段交点"是一种非常基础的几何计算, 在很多游戏中都会被使用到. 下面我就现学现卖的把最近才学会的一些"求线段交点"的算法说一说, 希望对大家有所帮助. 本 ...

  5. 平面内,线与线 两条线找交点 两条线段的位置关系(相交)判定与交点求解 C#

    个人亲自编写.测试,可以正常使用   道理看原文,这里不多说   网上找到的几篇基本都不能用的   C#代码 bool Equal(float f1, float f2) { return (Math ...

  6. 两条线段求交点+叉积求面积 poj 1408

    题目链接:https://vjudge.net/problem/POJ-1408 题目是叫我们求出所有四边形里最大的那个的面积. 思路:因为这里只给了我们正方形四条边上的点,所以我们要先计算横竖线段两 ...

  7. 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 ...

  8. 判断线段和直线相交 POJ 3304

    // 判断线段和直线相交 POJ 3304 // 思路: // 如果存在一条直线和所有线段相交,那么平移该直线一定可以经过线段上任意两个点,并且和所有线段相交. #include <cstdio ...

  9. 2015南阳CCPC D - Pick The Sticks dp

    D - Pick The Sticks Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description The story happened lon ...

随机推荐

  1. [转] JavaScript 和事件

    与浏览器进行交互的时候浏览器就会触发各种事件.比如当我们打开某一个网页的时候,浏览器加载完成了这个网页,就会触发一个 load 事件:当我们点击页面中的某一个“地方”,浏览器就会在那个“地方”触发一个 ...

  2. eslint error

    暂时不想解决 报错: 3:16 error Component should be written as a pure function react/prefer-stateless-function ...

  3. Markdown写接口文档,自动添加TOC

    上回说到,用Impress.js代替PPT来做项目展示.这回换Markdown来做接口文档好了.(不敢说代替Word,只能说个人感觉更为方便)当然,还要辅之以Git,来方便版本管理. Markdown ...

  4. 常用的 css 命名规则

    头:header 内容:content/container 尾:footer 导航:nav 侧栏:sidebar 栏目:column 页面外围控制整体布局宽度:wrapper 左右中:left rig ...

  5. 使用CDN加载jQuery类库后备代码

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></ ...

  6. object转化为string

    package common; import java.util.ArrayList; import java.util.List; public class DataZh { public stat ...

  7. SQL语句之二建表

    use Test --进入需要建表的数据库if exists(select * from sysobjects where name='MyTable')--表是否已经存在drop table MyT ...

  8. dedecms修改templets为别的名字

    修改templets模板文件夹的方法: 首先找到系统配置文件common.inc.php,此文件存放在Include目录下,打开common.inc.php来修改默认模板目录templets, 查找: ...

  9. PHP随机生成指定时间段的指定个数时间

    /** * 生成某个范围内的随机时间 * @param <type> $begintime 起始时间 格式为 Y-m-d H:i:s * @param <type> $endt ...

  10. 织梦 dedecms 中LOOP 万能标签循环 调用 arcurl标签(获取链接)

    在DEDECMS中,提供了loop万能循环标签,但是此循环标签只能循环出该表中的字段,而“[field:arcurl/]”链接标签并不能被解析出来,而DEDECMS官方论坛上也没有找到相关的解决办法, ...