計蒜客 商湯科技的行人檢測(困難)
阿新 • • 發佈:2019-01-31
觀察列出來的式子,發現對於某一個點實際上是四個未知數兩個方程,有無窮多個解。但是和另外一個點聯立就可以解出來了。這樣的話我們列舉兩個點再驗證,複雜度
如果我們隨機兩個點,有
當然求的時候也不要真的解四元方程組。觀察一下還是很容易用計算幾何的方法求出來的。
#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");
}