BZOJ 2592 随机化(伪)

思路:

放yousiki大爷题解

http://yousiki.net/index.php/archives/82/

我写的是随机化

既然gzz证了最终答案的上界是O(N)

那么我们可以n^2枚举所有的点对

先pretest判一发 (随机10个点  找找有没有对称点)  如果过了pretest再O(n)的判

整体复杂度是$O(n^2logn)$的

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int mod=10000019,N=1050;
int n,xx,yy,ans=0;
struct Point{double x,y;Point(){}Point(double X,double Y){x=X,y=Y;}}point[N];
Point operator-(Point a,Point b){return Point(a.x-b.x,a.y-b.y);}
double operator*(Point a,Point b){return a.x*b.y-a.y*b.x;}
bool operator<(Point a,Point b){if(a.x==b.x)return a.y<b.y;return a.x<b.x;}
struct Line{Point a,b;Line(){}Line(Point X,Point Y){a=X,b=Y;}}stk[N*100];
Line get_line(int i,int j){
    Point x=Point((point[i].x+point[j].x)/2,(point[i].y+point[j].y)/2);
    Point y=Point(x.x+point[j].y-point[i].y,x.y-point[j].x+point[i].x);
    return Line(x,y);
}
double dis(Point a,Point b){a=a-b;return sqrt(a.x*a.x+a.y*a.y);}
Point get_point(Point p,Line ln){
    double d=(ln.b-ln.a)*(p-ln.a)/dis(ln.a,ln.b)*2,x=ln.b.y-ln.a.y,y=ln.a.x-ln.b.x,s=sqrt(x*x+y*y);
    return Point(p.x+x*d/s,p.y+y*d/s);
}
bool pretest(Line ln){
    for(int i=1;i<=10;i++){
        Point p=get_point(point[rand()%n+1],ln);
        double x=round(p.x),y=round(p.y);
        if(abs(x-p.x)>1e-7||abs(y-p.y)>1e-7)return 0;
        Point f=Point(x,y);
        int t=lower_bound(point+1,point+1+n,f)-point;
        if(t>n||abs(point[t].x-f.x)>1e-7||abs(point[t].y-f.y)>1e-7)return 0;
    }return 1;
}
bool test(Line ln){
    for(int i=1;i<=n;i++){
        Point p=get_point(point[i],ln);
        double x=round(p.x),y=round(p.y);
        if(abs(x-p.x)>1e-7||abs(y-p.y)>1e-7)return 0;
        Point f=Point(x,y);
        int t=lower_bound(point+1,point+1+n,f)-point;
        if(t>n||abs(point[t].x-f.x)>1e-7||abs(point[t].y-f.y)>1e-7)return 0;
    }return 1;
}
bool check(Line tmp){for(int i=1;i<=ans;i++)if(abs((stk[i].a-stk[i].b)*(tmp.a-tmp.b))<1e-7)return 0;return 1;}
int main(){
    srand(1005730820);scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&xx,&yy),point[i]=Point(1.0*xx,1.0*yy);
    sort(point+1,point+1+n);
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++){
            Line tmp=get_line(i,j);
            if(check(tmp)&&pretest(tmp)&&test(tmp))stk[++ans]=tmp;
            tmp=Line(point[i],point[j]);
            if(check(tmp)&&pretest(tmp)&&test(tmp))stk[++ans]=tmp;
        }
    printf("%d
",ans);
}
原文地址:https://www.cnblogs.com/SiriusRen/p/6993176.html