如果发现广告等破坏行为,请尽量将条目恢复到较早的版本而不是把相应内容直接删除,谢谢合作。

URAL/1046

来自"NOCOW"

跳转到: 导航, 搜索

一道很复杂的几何题,在以M1为原点,水平方向为x轴的平面直角坐标系中,把点A1到A2的变换我们看作向量A1旋转alpha角度得到A2,也就是说我们可以用A1表示A2,怎么表示:

设A1=(x,y)

先把A1用极坐标表示

A1=(r,theta)

那么A2=(r,theta+alpha);

换成直角坐标

A2=(r*cos(theta+alpha),r*sin(theta+alpha))

用和角公式展开

A2=(r*cos(theta)*cos(alpha)-r*sin(theta)*sin(alpha),r*sin(theta)*cos(alpha)+r*cos(theta)*sin(alpha))

所以A2=(x*cos(alpha)-y*sin(alpha),y*cos(alpha)+x*sin(alpha))

我们再来看以(0,0)为原点,水平方向为x轴的平面直角坐标系中A1绕M1旋转alpha度得到A2,那么A2怎么表示

设M1=(mx,my)

不难看出

A2=((x-mx)*cos(alpha)-(y-my)*sin(alpha)+mx,(y-my)*cos(alpha)+(x-mx)*sin(alpha)+my)

好,这样就求出了A2用A1的线性表示(线性非常要)弄懂了这一步后我们想A1表示A2,A2表示A3,A3表示A4……An-1表示An,An表示A1,我们就可以得到两个关于A1的二元一次方程(横坐标产生一个,纵坐标产生一个),是不是可以把A1求出来,那么剩下的点都可以求出来了。

实现的时候我们设A1=(x,y),那么Ai就可以表示为ax+by+c,其中c为常数项。

program cao;
const
  maxn=100;
 
type
  expression=record
    a,b,c:extended;  //a means how much x1,b means how much y1,c means constant
  end;
 
  vector=record
    x,y:expression;
  end;
 
  point=record
    x,y:extended;
  end;
 
var
  t:array[0..maxn] of vector;
  m:array[0..maxn] of point;
  angle:array[0..maxn] of extended;
  a,b,c,d,e,f,g,h,i,j,k,l,n,p,q:longint;
  x,y,co,si:extended;
 
procedure init;
begin
  read(n);
  for i:=1 to n do
    read(m[i].x,m[i].y);
  for i:=1 to n do
    read(angle[i]);
  for i:=1 to n do
    angle[i]:=angle[i]*pi/180;
end;
 
procedure workout_linear_equations(var x,y:extended;a,b,c,d:expression);
begin
  a.a:=a.a-c.a; a.b:=a.b-c.b; a.c:=a.c-c.c;
  b.a:=b.a-d.a; b.b:=b.b-d.b; b.c:=b.c-d.c;
  x:=(a.c*b.b-b.c*a.b)/(b.a*a.b-a.a*b.b);
  y:=(a.c*b.a-b.c*a.a)/(b.b*a.a-a.b*b.a);
end;
 
procedure main;
begin
  t[1].x.a:=1;
  t[1].y.b:=1;
  for i:=1 to n do
  begin
    co:=cos(angle[i]);
    si:=sin(angle[i]);
    t[i+1].x.a:=t[i].x.a*co-t[i].y.a*si;
    t[i+1].x.b:=t[i].x.b*co-t[i].y.b*si;
    t[i+1].x.c:=(t[i].x.c-m[i].x)*co-(t[i].y.c-m[i].y)*si+m[i].x;
    t[i+1].y.a:=t[i].y.a*co+t[i].x.a*si;
    t[i+1].y.b:=t[i].y.b*co+t[i].x.b*si;
    t[i+1].y.c:=(t[i].x.c-m[i].x)*si+(t[i].y.c-m[i].y)*co+m[i].y;
  end;
  workout_linear_equations(x,y,t[n+1].x,t[n+1].y,t[1].x,t[1].y);
end;
 
procedure print;
begin
  for i:=1 to n do
    writeln(t[i].x.a*x+t[i].x.b*y+t[i].x.c:0:2,‘ ‘,t[i].y.a*x+t[i].y.b*y+t[i].y.c:0:2);
end;
 
begin
  init;
  main;
  print;
end.
个人工具