快到省选了,赶紧学一发计算几何……
这玩意就是线性规划.
半平面通常用不等式或者两点表示,具体表示方法,就题而言,要灵活.
算法的话,什么朴素O(n^2),什么分治,都不会,只会一个弹栈的.
这个算法的话,一开始好像一定要去重,而且有的时候需要在外面加4个框,似乎是因为这个算法在相邻直线的极角跨度大于Pi的时候就不对了……似乎还是为了保证判断无解的方法(剩余直线小于3个)的正确性……
反正我就大概懂一些计算几何基础(向量啊什么的),并且感性理解了一发这个算法……
就做了几道水题:

#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=10010;
struct Race{
    double k,b;
    int id;
}race[N],stack[N];
int top;
inline bool comp(Race a,Race b){
    return a.k<b.k||(a.k==b.k&&a.b>b.b);
}
int n;
bool good[N];
inline void Init(){
    scanf("%d",&n);
    int i;
    for(i=1;i<=n;++i)
        scanf("%lf",&race[i].b);
    for(i=1;i<=n;++i)
        scanf("%lf",&race[i].k),race[i].id=i;
}
inline bool check(Race a,Race b,Race c){
    double x=(double)(b.b-a.b)/(a.k-b.k);
    double y=a.k*x+a.b;
    return y>=c.k*x+c.b;
}
inline void Work(){
    int i,j;
    std::sort(race+1,race+(n+1),comp);
    j=0;
    race[++j]=race[1];
    for(i=2;i<=n;++i)
        if(race[i].k!=race[j].k||(race[i].k==race[j].k&&race[i].b==race[j].b))
            race[++j]=race[i];
    stack[++top]=(Race){1./0.,0.,0};
    for(i=1;i<=j;++i){
        while(top>1&&!check(stack[top],stack[top-1],race[i]))--top;
        stack[++top]=race[i];
    }
}
inline void Print(){
    int i;
    for(i=1;i<=top;++i)
        good[stack[i].id]=true;
    printf("%d\n",top-1);
    for(i=1;i<=n;++i)
        if(good[i])
            printf("%d ",i);
    puts("");
}
int main(){
    Init(),Work(),Print();
    return 0;
}
bzoj3190:[JLOI2013]赛车

相关文章:

  • 2022-12-23
  • 2021-11-07
  • 2021-07-31
  • 2022-02-11
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-06-14
  • 2021-01-06
  • 2022-12-23
相关资源
相似解决方案