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

与世无争的帅哥 提交于 2019-11-26 10:21:53
  • 题意: 在二维平面给出很多棍子,求在最上面的棍子(不被覆盖)
  • 思路: 从前向后枚举线段是否跟后面线段有交点即可
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define ll long long
#define FOR(i,l,r) for(int i = l ; i <= r ;++i )
#define inf 1<<30
#define eps (1e-9)
#define ALL(T)  T.begin(),T.end()
#define lson(i)     i<<1
#define rson(i)     (i<<1|1)
using namespace std;
typedef pair<int,int> pii;
const int maxn = 100010;
int sgn(double a){
    if(fabs(a)<eps) return 0;
    if(a>0) return 1;
    return -1;
}
struct point{
    double x,y;
    point(){}
    point(double _x,double _y):x(_x),y(_y){}
    void input(){
        scanf("%lf%lf",&x,&y);
    }
    point operator - (point b){
        return point(x-b.x,y-b.y);
    }
};
double sqr(double a){return a*a;}
double det(point a,point b){    //叉乘
    return a.x * b.y - a.y * b.x;
}
struct line{
    point a,b;
    line(){}
    line(point _a,point _b):a(_a),b(_b){}
};
int n;
int vis[maxn];
int check(line la,line lb){
    // 端点均在线段两边,即为有交点
    if(sgn(det(la.a-lb.a,la.b-lb.a))*sgn(det(la.a-lb.b,la.b-lb.b))==-1
        && sgn(det(lb.a-la.a,lb.b-la.a))*sgn(det(lb.a-la.b,lb.b-la.b))==-1)
        return true;
    return false;

}
vector<line> ve;
void solve(){
    ve.clear();
    memset(vis,0,sizeof vis);
    point a,b;
    FOR(i,1,n){
        scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
        ve.push_back(line(a,b));
    }
    FOR(i,0,n-1){
        FOR(j,i+1,n-1){
            // printf("%lf %lf ",ve[i].a.x,ve[i].a.y);
            if(check(ve[i],ve[j])){
                vis[i] = 1;
                break;
            }
        }
    }
    printf("Top sticks:");
    int first = 1;
    FOR(i,0,n-1){
        if(!vis[i]){
            if(!first){
                printf(",");
            }
            printf(" %d",i+1);
            first = 0;
        }
    }
    printf(".\n");
}

int main(){
    while(scanf("%d",&n) && n!=0){
        solve();
    }

    return 0;
}

我们可以通过det的符号判断点对于线段的相对位置: 大于零右侧,小于零左侧,等于零在线段上

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!