POJ 2653 Pick-up sticks【线段相交】

题意:n根木棍随意摆放在一个平面上,问放在最上面的木棍是哪些。

思路:线段相交,因为题目说最多有1000根在最上面。所以从后往前处理,直到木棍没了或者最上面的木棍的总数大于1000.

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
using namespace std;
const int N=1e5+111;
const double eps=1e-8;
int sgn(double x){
    if(fabs(x)<eps)    return 0;
    if(x>0)    return 1;
    return -1;
}
struct point{
    double x,y;
    point(){}
    point(double x_,double y_){
        x=x_,y=y_;
    }
    point operator -(const point &b)const{
        return point(x-b.x,y-b.y);
    }
    double operator *(const point &b)const{
        return x*b.x+y*b.y;
    }
    double operator ^(const point &b)const{
        return x*b.y-y*b.x;
    }
};
struct line{
    point s,e;
    line(){}
    line(point s_,point e_){
        s=s_,e=e_;
    }
}li[N];
double cal(point p0,point p1,point p2){//叉积
    return (p1-p0)^(p2-p0);
}
int xj(line a,line b){//判断两线段是否相交
    point A=a.s,B=a.e,C=b.s,D=b.e;
    return
    max(A.x,B.x)>=min(C.x,D.x) &&
    max(C.x,D.x)>=min(A.x,B.x) &&
    max(A.y,B.y)>=min(C.y,D.y) &&
    max(C.y,D.y)>=min(A.y,B.y) &&
    sgn(cal(A,C,D))*sgn(cal(B,C,D))<=0 &&
    sgn(cal(C,A,B))*sgn(cal(D,A,B))<=0;
}
int ans[N];
int main(){
    int n,i,j,js;
    while(~scanf("%d",&n)&&n){
        double x1,x2,y1,y2;js=0;
        for(i=1;i<=n;i++){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            li[i]=line(point(x1,y1),point(x2,y2));
        }
        for(i=n;i&&js<1000;i--){
            for(j=i+1;j<=n;j++){
                if(xj(li[i],li[j]))
                    break;
            }
            if(j>n)    ans[++js]=i;
        }
        printf("Top sticks:");
        for(i=js;i;i--){
            printf(" %d%c",ans[i],i==1?‘.‘:‘,‘);
        }
        puts("");
    }
    return 0;
}
时间: 2024-11-08 17:50:06

POJ 2653 Pick-up sticks【线段相交】的相关文章

POJ 1269 Intersecting Lines(线段相交,水题)

Intersecting Lines 大意:给你两条直线的坐标,判断两条直线是否共线.平行.相交,若相交,求出交点. 思路:线段相交判断.求交点的水题,没什么好说的. struct Point{ double x, y; } ; struct Line{ Point a, b; } A, B; double xmult(Point p1, Point p2, Point p) { return (p1.x-p.x)*(p2.y-p.y)-(p1.y-p.y)*(p2.x-p.x); } bool

POJ 1066 Treasure Hunt(线段相交&amp;&amp;转换)

Treasure Hunt 大意:在一个矩形区域内,有n条线段,线段的端点是在矩形边上的,有一个特殊点,问从这个点到矩形边的最少经过的线段条数最少的书目,穿越只能在中点穿越. 思路:需要巧妙的转换一下这个问题,因为从一个点到终点不可能"绕过"围墙,只能穿过去,所以门是否开在中点是无所谓的,只要求四周线段中点到终点的线段与墙的最少交点个数即可.更进一步,实际上,只需判断四周围墙的所有点与终点的连线与内墙的最少交点加一即可. struct Point{ double x, y; } A,

POJ 2653 Pick-up sticks [线段相交 迷之暴力]

Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12861   Accepted: 4847 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 fin

【POJ 2653】Pick-up sticks 判断线段相交

一定要注意位运算的优先级!!!我被这个卡了好久 判断线段相交模板题. 叉积,点积,规范相交,非规范相交的简单模板 用了“链表”优化之后还是$O(n^2)$的暴力,可是为什么能过$10^5$的数据? #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define N 100005 using namespace std; struct Point { double x

POJ 2653 Pick-up sticks(线段相交)

题意:给定n个木棍依次放下,要求最终判断没被覆盖的木棍是哪些. 思路:快速排斥以及跨立实验可以判断线段相交. 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 const double eps=1e-10; 7 struct Point{ 8 double x,y; 9 Point(){} 10

POJ 1410 Intersection --几何,线段相交

题意: 给一条线段,和一个矩形,问线段是否与矩形相交或在矩形内. 解法: 判断是否在矩形内,如果不在,判断与四条边是否相交即可.这题让我发现自己的线段相交函数有错误的地方,原来我写的线段相交函数就是单纯做了两次跨立实验,在下图这种情况是错误的: 这样的话线段与右边界的两次跨立实验(叉积<=0)都会通过,但是并不相交. 所以要加快速排斥. 还有就是这题题目说给出的不一定是左上角,右下角依次的顺序.所以干脆重新自己定义左上角,右下角. 代码: #include <iostream> #inc

POJ 1066 Treasure Hunt (线段相交)

题意:给你一个100*100的正方形,再给你n条线(墙),保证线段一定在正方形内且端点在正方形边界(外墙),最后给你一个正方形内的点(保证不再墙上) 告诉你墙之间(包括外墙)围成了一些小房间,在小房间内可以从房间边界(墙)的中点走过这堵墙,问你从给定的点走到外墙外最少走过的墙数 题解:注意我们可以从每个房间的墙的中点走出,而不是一整条线段(墙)的中点走出.... 然后我们可以找四周的边界中的每个点与给定点的连线,再与给定的线段找相交最少的交点数就是答案 但是边界每个点是无穷多个,因此我们可以这样

POJ 3304 Segments[直线与线段相交]

Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13514   Accepted: 4331 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

POJ 2074 /// 判断直线与线段相交 视野盲区

题目大意: 将所有物体抽象成一段横向的线段 给定房子的位置和人行道的位置 接下来给定n个障碍物的位置 位置信息为(x1,x2,y) 即x1-x2的线段 y相同因为是横向的 求最长的能看到整个房子的一段人行道的长度 若不在 y(房子)和y(人行道)之间的 不会有视野的阻碍 注意边界处理 因为盲区可能包含在人行道内 也可能超出 #include <cstdio> #include <algorithm> #include <cmath> using namespace st

POJ - 2653 - Pick-up sticks 线段与线段相交

判断线段与线段相交 莫名其妙的数据量 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cmath> 5 #include <cstring> 6 using namespace std; 7 const double eps = 1e-8; 8 int dcmp(double x) 9 { 10 return fabs(x) < eps ?