BZOJ1007 HNOI2008 水平可见直线 计算几何

题意:给定N条直线,求由这N条直线组成的,满足上方没有直线交点的边界由哪些直线组成
题解:我这STL用的真是闷声做大死,多亏不卡常……显然所求的边界中的直线k肯定单调的,所以首先将直线按k升序(第一关键字),b降序(第二关键字)进行排序。然后枚举每一条直线,用单调栈s维护这个直线集,若堆顶元素s[0]能被次栈顶直线s[1]和当前直线覆盖l[i],则满足s[0]与l[i]的交点在s[1]与s[0]交点的左侧,按照这一规则不断弹栈,然后加入l[i]。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int MAXN=50000+2;
struct Line{
    int t;
    double k,b;
    Line(){}
    Line(double _k,double _b):k(_k),b(_b){}
}l[MAXN];
struct Point{
    double x,y;
};
int N;
vector<Line> s;

bool cmp1(Line x,Line y){ return x.k==y.k?x.b>y.b:x.k<y.k;}

bool cmp2(Line x,Line y){ return x.t<y.t;}

Point Calc(Line x,Line y){
    Point ans;
    ans.x=(y.b-x.b)/(x.k-y.k),ans.y=ans.x*x.k+x.b;
    return ans;
}

int main(){
    cin >> N;
    for(int i=1;i<=N;i++) cin >> l[i].k >> l[i].b,l[i].t=i;

    sort(l+1,l+N+1,cmp1),s.push_back(l[1]);
    for(int i=2;i<=N;i++){
        while(s.size()>1 && Calc(l[i],s[0]).x<=Calc(s[0],s[1]).x) s.erase(s.begin());
        s.insert(s.begin(),l[i]);
    }

    N=s.size(),sort(s.begin(),s.end(),cmp2);
    for(int i=0;i<N;i++) cout << s[i].t << " ";

    return 0;
}
View Code

 

posted @ 2017-02-26 02:07  WDZRMPCBIT  阅读(150)  评论(0编辑  收藏  举报