您的位置:首页 > 其它

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

2017-05-31 16:55 309 查看

传送门 https://nanti.jisuanke.com/t/15553

 

数学问题 计算几何

好题好题。

一对坐标可以列出两个方程,两对坐标就可以解出一组四个量。

随机选两个点,解出四个参数,O(n)验证一遍。由于最少有一半的点是正确记录的,随机选点找到正确答案的概率不会小于1/4,错误概率不会大于3/4,所以随机选个几十次,正确率就上升到99%+了。

——什么?这样你也没选到正确的点?

——非洲部落欢迎你

 

用计算几何的知识可以轻松地解出四个参数:

角度:转化后两点成的直线与转化前两点成的直线的夹角即为答案,我们利用atan2(x,y)求解。

倍数:转化后两点的距离/转化前两点的距离。

x,y:直接减。

  ——by ShinyaLicone

你也许会有可以用解析几何强行解的错觉。

那只是错觉。

 

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const double eps=1e-4;
const double pi=cos(-1.0);
const int mxn=100010;
struct point{
double x,y;
point(){}
point(double _x,double _y):x(_x),y(_y){}
point operator + (const point &b){return point(x+b.x,y+b.y);}
point operator - (const point &b){return point(x-b.x,y-b.y);}
point operator * (const double v){return point(x*v,y*v);}
point operator / (const double v){return point(x/v,y/v);}
double operator * (const point &b){return x*b.x+y*b.y;}
}a[mxn],b[mxn];
inline double Cross(const point &a,const point &b){
return a.x*b.y-a.y*b.x;
}
inline double angle(const point a){
return atan2(a.y,a.x);
}
inline double Dist(const point &a,const point &b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
//

int n;
double ang,dx,dy,sc;
point spin(point a,double ang){
return point(a.x*cos(ang)-a.y*sin(ang),a.x*sin(ang)+a.y*cos(ang));
}
void Calc(int x,int y){
ang=angle(b[y]-b[x])-angle(a[y]-a[x]);
sc=Dist(b[y],b[x])/Dist(a[y],a[x]);
point res=spin(a[x],ang)*sc;
dx=b[x].x-res.x;
dy=b[x].y-res.y;
return;
}
bool check(){
int c1=0,c2=0;
for(int i=1;i<=n;i++){
point res=spin(a[i],ang)*sc+point(dx,dy);
//        printf("res:%.3f %.3f\n",res.x,res.y);
if(fabs(b[i].x-res.x)<eps && fabs(b[i].y-res.y)<eps)c1++;//right
else c2++;//wrong
if(c2*2>n)return 0;
}
return 1;
}
int main(){
//    freopen("in.txt","r",stdin);
int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%lf%lf",&a[i].x,&a[i].y);
scanf("%lf%lf",&b[i].x,&b[i].y);
}
if(n==1){
printf("%.12lf\n%.12lf\n%.12lf %.12lf\n",0.0,1.0,b[1].x-a[1].x,b[1].y-a[1].y);
return 0;
}
srand(19260817);
int T=50;
while(T){
T--;
//        printf("T:%d\n",T);
int a=((rand()%n+1)+(rand()%n+1)+(rand()%n+1))%n+1;
int b=((rand()%n+1)+(rand()%n+1)+(rand()%n+1))%n+1;
if(a==b)continue;
//        printf("calc:%d %d\n",a,b);
Calc(a,b);
//        printf("res:%.12lf %.12lf %.12lf %.12lf\n",ang,sc,dx,dy);
if(check()){
printf("%.10lf\n%.10lf\n%.10lf %.10lf\n",ang,sc,dx,dy);
return 0;
}
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: