计蒜客 商汤科技的行人检测

传送门 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 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/6924975.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值