hdu 1147(线段相交)

Pick-up sticks

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2673    Accepted Submission(s): 975

Problem 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根stick,从第一根开始扔到平面上,第i根有可能覆盖前1-(i-1)的某些stick,求最后还有多少stick没有被覆盖.

分析:判断线段是否相交即可。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int N = 100005;
struct Point{
    double x,y;
}p[2*N];

///叉积
double mult(Point a, Point b, Point c)
{
    return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}

///a, b为一条线段两端点c, d为另一条线段的两端点 相交返回true, 不相交返回false
bool isCross(Point a, Point b, Point c, Point d)
{
    if (max(a.x,b.x)<min(c.x,d.x))return false;
    if (max(a.y,b.y)<min(c.y,d.y))return false;
    if (max(c.x,d.x)<min(a.x,b.x))return false;
    if (max(c.y,d.y)<min(a.y,b.y))return false;
    if (mult(c, b, a)*mult(b, d, a)<0)return false;
    if (mult(a, d, c)*mult(d, b, c)<0)return false;
    return true;
}
bool under[N]; ///记录哪些stick在下面
int ans[N];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF,n){
        memset(under,false,sizeof(under));
        int k=1;
        for(int i=1;i<=n;i++){
            scanf("%lf%lf%lf%lf",&p[k].x,&p[k].y,&p[k+1].x,&p[k+1].y);
            k+=2;
        }
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                if(isCross(p[2*i-1],p[2*i],p[2*j-1],p[2*j])) {
                    under[i]=true;
                    break;
                }
            }
        }

        printf("Top sticks: ");
        int t=0;
        for(int i=1;i<=n;i++){
            if(!under[i]) ans[t++]=i;
        }
        for(int i=0;i<t-1;i++){
            printf("%d, ",ans[i]);
        }
        printf("%d.\n",ans[t-1]);
    }
    return 0;
}
时间: 2024-10-18 23:59:43

hdu 1147(线段相交)的相关文章

hdu 1558 (线段相交+并查集) Segment set

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐标,当输入Q的时候输入n,然后输出与第n条线段相交的线段有多少条 首先判断线段是否相交,在算法导论p577上有介绍 线段A(x1,y1)-B(x2,y2),所在直线L1方程为F1(x,y)=0;线段C(x3,y3)-D(x4,y4),所在直线L2方程为F2(x,y)=0; 如何判断两条线段有交点:(

hdu 1558 线段相交+并查集

题意:要求相交的线段都要塞进同一个集合里 sol:并查集+判断线段相交即可.n很小所以n^2就可以水过 1 #include <iostream> 2 #include <cmath> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 int f[1010]; 8 char ch; 9 int tmp,n; 10 double X1,X2,Y1,Y2; 11 12 #def

hdu 1558 线段相交+并查集路径压缩

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3457    Accepted Submission(s): 1290 Problem Description A segment and all segments which are connected with it compose a segment set.

HDU 1086 You can Solve a Geometry Problem too(判断线段相交)

题目地址:HDU 1086 就这么一道仅仅判断线段相交的题目写了2k多B的代码..是不是有点浪费...但是我觉得似乎哪里也优化不了了.... 判断线段相交就是利用的叉积.假如现在两条线段分别是L1和L2,先求L1和L2两个端点与L1的某个端点的向量的叉积,如果这两个的叉积的乘积小于0的话,说明L1在是在L2两个端点之间的,但此时并不保证一定相交.此时需要用同样的方法去判断L2是否在L1的两个端点之间,如果L2也在L1的两个端点之间的话,那就足以说明L1与L2相交.但是这题还需要判断是否端点也相交

HDU 4063 线段与圆相交+最短路

Aircraft Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 980    Accepted Submission(s): 228 Problem Description You are playing a flying game. In the game, player controls an aircraft in a 2D-

hdu 1086(判断线段相交)

传送门:You can Solve a Geometry Problem too 题意:给n条线段,判断相交的点数. 分析:判断线段相交模板题,快速排斥实验原理就是每条线段代表的向量和该线段的一个端点与 另一条线段的两个端点构成的两个向量求叉积,如果线段相交那么另一条线段两个端点必定在该线段的两边,则该线段代表的向量必定会顺时针转一遍逆时针转一遍,叉积必定会小于等于0,同样对另一条线段这样判断一次即可. #include <algorithm> #include <cstdio>

HDU 3492 (直线与所有线段相交) Segment

题意: 给出n个线段,判断是否存在一条直线使得所有线段在直线上的射影的交非空. 分析: 如果我们找到一条与所有线段相交的直线,然后做一条与该直线垂直的直线,这些线段在直线上的射影就一定包含这个垂足. 所以我们只要判断是否存在一条直线与所有的点相交即可. 如果存在这样一条直线,那么将这条直线平移或者旋转,就会被这些线段中的某两个端点“卡”住. 所以我们枚举两个端点,然后判断这些线段是否与这两个点所在的直线都相交即可. 本以为是一道很简单的计算几何,结果卡了好几天. 看了别人的题解,才发现问题所在.

hdu 3304(直线与线段相交)

Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12042   Accepted: 3808 Description Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments

hdu 4606 Occupy Cities(线段相交+最小路径覆盖+二分)

Occupy Cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1178    Accepted Submission(s): 388 Problem Description The Star Wars is coming to an end as the Apple Planet is beaten by the Ban