您的位置:首页 > 其它

计蒜客 商汤科技的行人检测(困难)

2017-05-30 09:43 176 查看
观察列出来的式子,发现对于某一个点实际上是四个未知数两个方程,有无穷多个解。但是和另外一个点联立就可以解出来了。这样的话我们枚举两个点再验证,复杂度O(n3)可以通过中等难度。

如果我们随机两个点,有0.25的概率正确,这就意味着多试几次就可以了。比如试20次,正确的概率是0.997。

当然求的时候也不要真的解四元方程组。观察一下还是很容易用计算几何的方法求出来的。

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-4;
const int maxn=100010;
int cmp(double x)
{
if (x>=eps) return 1;
if (fabs(x)<eps) return 0;
return -1;
}
struct Vector
{
double x,y;
void rd()
{
scanf("%lf%lf",&x,&y);
}
void wt()
{
printf("%.10f %.10f\n",x,y);
}
bool operator == (const Vector &v) const
{
return cmp(x-v.x)==0&&cmp(y-v.y)==0;
}
Vector operator + (const Vector &v) const
{
return (Vector){x+v.x,y+v.y};
}
Vector operator - (const Vector &v) const
{
return (Vector){x-v.x,y-v.y};
}
Vector operator * (const double &k) const
{
return (Vector){x*k,y*k};
}
}a[maxn],b[maxn];
typedef Vector Point;
double dot(Vector v,Vector u)
{
return v.x*u.x+v.y*u.y;
}
double cross(Vector v,Vector u)
{
return v.x*u.y-v.y*u.x;
}
Vector rot(Vector v,double a)
{
return (Vector){cos(a)*v.x-sin(a)*v.y,sin(a)*v.x+cos(a)*v.y};
}
double angle(Vector v)
{
return atan2(v.y,v.x);
}
double len(Vector v)
{
return sqrt(dot(v,v));
}
double dis(Point p,Point q)
{
return len(p-q);
}
int n;
int check(double Theta,double Scale,Vector D)
{
int cnt=0;
for (int i=1;i<=n;i++)
if (!(rot(a[i],Theta)*Scale+D==b[i]))
{
cnt++;
if (cnt*2>n) return 0;
}
return 1;
}
int check(int u,int v)
{
double d1=dis(a[u],a[v]),d2=dis(b[u],b[v]),Scale=d2/d1,
Theta=angle(b[v]-b[u])-angle(a[v]-a[u]);
Vector D=b[u]-rot(a[u],Theta)*Scale;
if (check(Theta,Scale,D))
{
printf("%.10f\n%.10f\n",Theta,Scale);
D.wt();
return 1;
}
return 0;
}
int main()
{
//freopen("in","r",stdin);
int x,y;
srand(123);
int T=20;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
a[i].rd();
b[i].rd();
}
if (n==1)
{
printf("0\n1\n");
(b[1]-a[1]).wt();
return 0;
}
while (T--)
{
x=rand()%n+1;
y=rand()%n+1;
while (x==y) y=rand()%n+1;
if (check(x,y)) return 0;
}
/*for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
if (check(i,j)) return 0;*/
printf("1\n1\n1 1\n");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: