计蒜客 商汤科技的行人检测
传送门 https://nanti.jisuanke.com/t/15553
数学问题 计算几何
好题好题。
一对坐标可以列出两个方程,两对坐标就可以解出一组四个量。
随机选两个点,解出四个参数,O(n)验证一遍。由于最少有一半的点是正确记录的,随机选点找到正确答案的概率不会小于1/4,错误概率不会大于3/4,所以随机选个几十次,正确率就上升到99%+了。
——什么?这样你也没选到正确的点?
——非洲部落欢迎你
用计算几何的知识可以轻松地解出四个参数:
角度:转化后两点成的直线与转化前两点成的直线的夹角即为答案,我们利用atan2(x,y)求解。
倍数:转化后两点的距离/转化前两点的距离。
x,y:直接减。
——by ShinyaLicone
你也许会有可以用解析几何强行解的错觉。
那只是错觉。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 using namespace std; 7 const double eps=1e-4; 8 const double pi=cos(-1.0); 9 const int mxn=100010; 10 struct point{ 11 double x,y; 12 point(){} 13 point(double _x,double _y):x(_x),y(_y){} 14 point operator + (const point &b){return point(x+b.x,y+b.y);} 15 point operator - (const point &b){return point(x-b.x,y-b.y);} 16 point operator * (const double v){return point(x*v,y*v);} 17 point operator / (const double v){return point(x/v,y/v);} 18 double operator * (const point &b){return x*b.x+y*b.y;} 19 }a[mxn],b[mxn]; 20 inline double Cross(const point &a,const point &b){ 21 return a.x*b.y-a.y*b.x; 22 } 23 inline double angle(const point a){ 24 return atan2(a.y,a.x); 25 } 26 inline double Dist(const point &a,const point &b){ 27 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 28 } 29 // 30 31 int n; 32 double ang,dx,dy,sc; 33 point spin(point a,double ang){ 34 return point(a.x*cos(ang)-a.y*sin(ang),a.x*sin(ang)+a.y*cos(ang)); 35 } 36 void Calc(int x,int y){ 37 ang=angle(b[y]-b[x])-angle(a[y]-a[x]); 38 sc=Dist(b[y],b[x])/Dist(a[y],a[x]); 39 point res=spin(a[x],ang)*sc; 40 dx=b[x].x-res.x; 41 dy=b[x].y-res.y; 42 return; 43 } 44 bool check(){ 45 int c1=0,c2=0; 46 for(int i=1;i<=n;i++){ 47 point res=spin(a[i],ang)*sc+point(dx,dy); 48 // printf("res:%.3f %.3f\n",res.x,res.y); 49 if(fabs(b[i].x-res.x)<eps && fabs(b[i].y-res.y)<eps)c1++;//right 50 else c2++;//wrong 51 if(c2*2>n)return 0; 52 } 53 return 1; 54 } 55 int main(){ 56 // freopen("in.txt","r",stdin); 57 int i,j; 58 scanf("%d",&n); 59 for(i=1;i<=n;i++){ 60 scanf("%lf%lf",&a[i].x,&a[i].y); 61 scanf("%lf%lf",&b[i].x,&b[i].y); 62 } 63 if(n==1){ 64 printf("%.12lf\n%.12lf\n%.12lf %.12lf\n",0.0,1.0,b[1].x-a[1].x,b[1].y-a[1].y); 65 return 0; 66 } 67 srand(19260817); 68 int T=50; 69 while(T){ 70 T--; 71 // printf("T:%d\n",T); 72 int a=((rand()%n+1)+(rand()%n+1)+(rand()%n+1))%n+1; 73 int b=((rand()%n+1)+(rand()%n+1)+(rand()%n+1))%n+1; 74 if(a==b)continue; 75 // printf("calc:%d %d\n",a,b); 76 Calc(a,b); 77 // printf("res:%.12lf %.12lf %.12lf %.12lf\n",ang,sc,dx,dy); 78 if(check()){ 79 printf("%.10lf\n%.10lf\n%.10lf %.10lf\n",ang,sc,dx,dy); 80 return 0; 81 } 82 } 83 return 0; 84 }
本文为博主原创文章,转载请注明出处。