快到省选了,赶紧学一发计算几何……
这玩意就是线性规划.
半平面通常用不等式或者两点表示,具体表示方法,就题而言,要灵活.
算法的话,什么朴素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; }