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. (转载)Linux下安装配置MySQL+Apache+PHP+WordPress的详细笔记

    Linux下安装配置MySQL+Apache+PHP+WordPress的详细笔记 Linux下配LMAP环境,花了我好几天的时间.之前没有配置过,网上的安装资料比较混乱,加上我用的版本问题,安装过程 ...

  2. CSS块级元素、内联元素概念

    CSS文档流与块级元素(block).内联元素(inline),之前翻阅不少书籍,看过不少文章, 看到所多的是零碎的CSS布局基本知识,比较表面.看过O'Reilly的<CSS权威指南>, ...

  3. HTML5之填写个人信息

  4. 用Javascript进行HTML转义(分享)

      众所周知页面上的字符内容通常都需要进行HTML转义才能正确显示,尤其对于Input,Textarea提交的内容,更是要进行转义以防止javascript注入攻击.   通常的HTML转义主要是针对 ...

  5. 在Java控制台模拟dos命令下操作MySQL

    一.导入mysql的驱动:"com.mysql.jdbc.Driver", 必须将mysql的驱动 包(jar文件)导入到本工程中. Class.forName("com ...

  6. mac 下maven的安装

    最近在学习mahout,这些安装相关软件的步骤先记下来,避免以后忘记. 1.首先在mac上查看本机的java版本,如果没有需要自己去安装: 我的电脑上安装的java是1.7.0_79 2.在http: ...

  7. 常见的mongodb可视化工具

    一.MongoVue   1.MongoVUE是一款比较好用的MongoDB客户端工具,可以为大家提供一个高度.简洁可用的MongoDB管理界面. 2.通过MongoVUE,用户可以用树形.表格及bj ...

  8. MySql数据库2【常用命令行】

    (一) 连接MYSQL: 格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MYSQL 进入mysql安装目录下的bin目录下,再键入命令mysql -uroot -p,回 ...

  9. php 详解spl_autoload_register()函数

    在了解这个函数之前先来看另一个函数:__autoload. 一.__autoload 这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数.看下面例子: printit.c ...

  10. 阿里云的esc

    云服务器ecs作用如下:1.完全管理权限:对云服务器的操作系统有完全控制权,用户可以通过连接管理终端自助解决系统问题,进行各项操作:2.快照备份与恢复:对云服务器的磁盘数据生成快照,用户可使用快照回滚 ...