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 ...
随机推荐
- Mysql新建用户和数据库并授权
测试环境:Centos 6.3和Mysql 5.3 一.新建用户 //登录MYSQL@>mysql -u root -p@>密码//创建用户mysql> insert into my ...
- Jboss image upload and http access to show image--reference
question I am uploading images to jboss server by getting the absolute path using the following code ...
- [转] 学习React Native必看的几个开源项目
http://www.lcode.org/study-react-native-opensource-one/ http://gold.xitu.io/entry/575f498c128fe10057 ...
- jQuery日期联动插件
此版本为网上的日期联动插件修改版,加入了修改后事件 /* * jQuery Date Selector Plugin * 日期联动选择插件 * * Demo: $("#calendar&qu ...
- 网站分析统计JS源码分享
之前公司做了一个分析云平台,用来跟踪收集海量的用户行为的相关数据,供运营人员实时监控网站访问量,统计PV,UV,独立IP,访问时段,访问时长,热点追踪等多类信息,我用JS写了一个小插件,只需要再页面加 ...
- C# 霍夫曼二叉树压缩算法实现
知道有的人比较懒,直接贴全部代码. 一开始一次性Code完了压缩部分代码.只调试了2,3次就成功了. 一次性写150行代码,没遇到什么bug的感觉还是蛮爽的. 写解压代码,才发现压缩代码有些细节问题. ...
- 阿里云服务器如何安装memcached
方法/步骤 1 使用Xshell登陆阿里云服务器. 请使用root帐号登陆.下面的操作全部在home目录里执行 2 安装libevent. 输入命令 yum -y install libevent-d ...
- jdbc - Insert 'Date' value in PreparedStatement
“preparedStatement.setDate()”方法接受的是 'java.sql.Date' 类型的参数,而我们一般格式化日期所使用的是'java.util.Date'中的'SimpleDa ...
- 用WebStorm调试本地html(含嵌入的javascript).
题外话: 以前很少能调试,甚至以为不能调试(好笨),后来我看了一本叫做<<Learning Three.js>>的一本书后,里面推荐有几种javascript的编辑工具,都蛮好 ...
- 利用ASP.NET AJAX的Timer讓GridView每隔一段時間做到自動換頁的功能
最近在討論區看到這個問題,小弟利用asp.net ajax的timer來實作這個功能 利用timer每隔一段時間,讓gridview自動跳頁並且更新gridview的內容 asp.net(c#) Gr ...