给你N个点的坐标。现有一些操作,求执行完所有操作后这些点的坐标。
操作1:让这些点的坐标加上一些数;
操作2:让这些点的坐标乘上一些数;
操作3:让这些点绕着一个中心点顺时针旋转θ角度;
操作4:给定一个循环体和循环次数,循环执行循环体中的操作;(循环可以嵌套)
这里讲讲操作3怎么处理。
设x[i],y[i]为点的坐标。xx,yy为旋转中心的坐标。x1,y1为旋转后的点的坐标。
则
x1=(x[i]-xx)*cos(angle)-(y[i]-yy)*sin(angle)+xx;
y1=(y[i]-yy)*cos(angle)+(x[i]-xx)*sin(angle)+yy;
注意angle是弧度角。
模拟操作能得30分,AC不了主要是操作4循坏太慢。
怎么优化?
我们要思考怎样避免每次都模拟循环,一个直接的想法就是把循环作为一个整体保存下来,避免重复运行。
如何保存中间过程,我们注意到题目中的变换其实都是对于两个变量的线性递推,完全可以用矩阵来实现,这样根据矩阵的结合律,就可以把一堆变换作为整体保存。而循环多次就相当于把这个代表变换的矩阵乘几次,加上快速幂就能AC了。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define N 110
#define M 1010
#define pi M_PI
#define rad(x) x*pi/180
typedef double matrix[4][4];
using namespace std;
struct Operation
{
double x1,y1,angle;
int time,type;
}a[M];
int n,m,top,stack[M],end[M];
double x[N],y[N];
matrix H;
char ch;
void mul(matrix a,matrix b)
{
matrix c;
memset(c,0,sizeof(c));
fo(k,1,3)
fo(i,1,3)
fo(j,1,3)
c[i][j]+=a[i][k]*b[k][j];
memcpy(a,c,sizeof(c));
}
void qmi(matrix &a,int x)
{
matrix c;
memset(c,0,sizeof(c));
fo(i,1,3) c[i][i]=1;
while(x>0)
{
if(x&1==1) mul(c,a);
mul(a,a);
x>>=1;
}
memcpy(a,c,sizeof(c));
}
void dg(int st,int en)
{
if(st>en) return;
matrix F,G;
memset(F,0,sizeof(F));
fo(i,1,3) F[i][i]=1;
fo(i,st,en)
{
memset(G,0,sizeof(G));
if(a[i].type==1)
{
G[1][1]=1;
G[2][2]=1;
G[3][1]=a[i].x1;
G[3][2]=a[i].y1;
G[3][3]=1;
mul(F,G);
}
if(a[i].type==2)
{
G[1][1]=a[i].x1;
G[2][2]=a[i].y1;
G[3][3]=1;
mul(F,G);
}
if(a[i].type==3)
{
a[i].angle=360-a[i].angle;
double s1=cos(rad(a[i].angle)),s2=sin(rad(a[i].angle));
G[1][1]=s1;
G[1][2]=s2;
G[2][1]=-s2;
G[2][2]=s1;
G[3][1]=s2*a[i].y1-s1*a[i].x1+a[i].x1;
G[3][2]=-s1*a[i].y1-s2*a[i].x1+a[i].y1;
G[3][3]=1;
mul(F,G);
}
if(a[i].type==4)
{
dg(i+1,end[i]-1);
qmi(H,a[i].time);
mul(F,H);
i=end[i];
}
}
memcpy(H,F,sizeof(F));
}
int main()
{
freopen("transform.in","r",stdin);
freopen("transform.out","w",stdout);
cin>>n;
fo(i,1,n) scanf("%lf%lf\n",&x[i],&y[i]);
while(scanf("%c",&ch)!=EOF)
{
m++;
if(ch=='T') a[m].type=1,scanf("rans(%lf,%lf)\n",&a[m].x1,&a[m].y1);
if(ch=='S') a[m].type=2,scanf("cale(%lf,%lf)\n",&a[m].x1,&a[m].y1);
if(ch=='R') a[m].type=3,scanf("otate(%lf,%lf,%lf)\n",&a[m].angle,&a[m].x1,&a[m].y1);
if(ch=='L') a[m].type=4,scanf("oop(%d)\n",&a[m].time);
if(ch=='E') a[m].type=5,scanf("nd\n");
}
int top=0;
fo(i,1,m)
if(a[i].type==4) stack[++top]=i;
else
if(a[i].type==5) end[stack[top--]]=i;
dg(1,m);
fo(i,1,n)
{
matrix F;
memset(F,0,sizeof(F));
F[1][1]=x[i],F[1][2]=y[i],F[1][3]=1;
mul(F,H);
printf("%.4lf %.4lf\n",F[1][1],F[1][2]);
}
fclose(stdin);fclose(stdout);
}