您的位置:首页 > 其它

【NOIP2013模拟联考14】图形变换(transform)

2017-09-25 20:09 477 查看

Description

翔翔最近接到一个任务,要把一个图形做大量的变换操作,翔翔实在是操作得手软,决定写个程序来执行变换操作。

翔翔目前接到的任务是,对一个由n个点组成的图形连续作平移、缩放、旋转变换。相关操作定义如下:

Trans(dx,dy) 表示平移图形,即把图形上所有的点的横纵坐标分别加上dx和dy;

Scale(sx,sy) 表示缩放图形,即把图形上所有点的横纵坐标分别乘以sx和sy;

Rotate(θ,x0,y0) 表示旋转图形,即把图形上所有点的坐标绕(x0,y0)顺时针旋转θ角度

由于某些操作会重复运行多次,翔翔还定义了循环指令:

Loop(m)



End

表示把Loop和对应End之间的操作循环执行m次,循环可以嵌套。

Data Constraint

保证操作中坐标值不会超过double范围,输出不会超过int范围;

指令总共不超过1000行;

对于所有的数据,所有循环指令中m<=1000000;

对于60%的数据,所有循环指令中m<=1000;

对于30%的数据不含嵌套循环。

Solution

这题我们首先要知道一个公式(旋转公式):

x′=x∗sinp−y∗cosp

y′=x∗cosp+y∗cosp

(p是角度)这是逆时针公式,所以再使用公式前应把角度取负。(注意注意!我这里被卡了很久!)

这样我们就可以做出来啦。

但是按照这样打,我们还是会超时,那怎么办呢?

加一个矩阵乘法优化(参考矩阵乘法)。坑死了,打了两个小时,才10分,发现没有取负,40分,然后最后发现公式写错了…….

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define Pi M_PI
using namespace std;
int n;
double x[101],y[101];
double p[4][4],ans[4],now[4][4],pcdy[4][4],ans2[4];
void time(int n)
{
int i,j,k;
double p1[4][4];
memset(p1,0,sizeof(p1));
for(i=1;i<=n;++i)
for(j=1;j<=n;++j)
for(k=1;k<=n;++k)
p1[i][j]+=p[i][k]*now[k][j];
memcpy(p,p1,sizeof(p1));
}
void dfs(int num)
{
char k1=getchar();
int i,j,m,k;
double dx,dy,sx,sy,x0,y0,an,an2;
double p2[4][4],p1[4][4],p3[4][4],p4[4][4];
memset(p2,0,sizeof(p2));
memset(p3,0,sizeof(p3));
for(i=1;i<=3;++i) p3[i][i]=1;
for(i=1;i<=3;++i) p2[i][i]=1;
while(k1!='E')
{
if(k1=='T')
{
scanf("rans(%lf,%lf)\n",&dx,&dy);
memset(now,0,sizeof(now));
for(i=1;i<=3;++i) now[i][i]=1;
now[3][1]=dx;now[3][2]=dy;
memset(p1,0,sizeof(p1));
for(i=1;i<=3;++i)
for(j=1;j<=3;++j)
for(k=1;k<=3;++k)
p1[i][j]+=p2[i][k]*now[k][j];
memcpy(p2,p1,sizeof(p1));
}
if(k1=='S')
{
scanf("cale(%lf,%lf)\n",&sx,&sy);
memset(now,0,sizeof(now));
now[1][1]=sx;now[2][2]=sy;now[3][3]=1;
memset(p1,0,sizeof(p1));
for(i=1;i<=3;++i)
for(j=1;j<=3;++j)
for(k=1;k<=3;++k)
p1[i][j]+=p2[i][k]*now[k][j];
memcpy(p2,p1,sizeof(p1));
}
if(k1=='R')
{
scanf("otate(%lf,%lf,%lf)\n",&an,&x0,&y0);
memset(p1,0,sizeof(now));
an2=(-an)*Pi/180;
now[1][1]=cos(an2);now[1][2]=sin(an2);
now[2][1]=-sin(an2);now[2][2]=cos(an2);
now[3][1]=x0+y0*sin(an2)-x0*cos(an2);
now[3][2]=y0-x0*sin(an2)-y0*cos(an2);now[3][3]=1;
memset(p1,0,sizeof(p1));
for(i=1;i<=3;++i)
for(j=1;j<=3;++j)
for(k=1;k<=3;++k)
p1[i][j]+=p2[i][k]*now[k][j];
memcpy(p2,p1,sizeof(p1));
}
if(k1=='L')
{
scanf("oop(%d)\n",&m);
dfs(m);
memcpy(now,pcdy,sizeof(pcdy));
memset(p1,0,sizeof(p1));
for(i=1;i<=3;++i)
for(j=1;j<=3;++j)
for(k=1;k<=3;++k)
p1[i][j]+=p2[i][k]*now[k][j];
memcpy(p2,p1,sizeof(p1));
}
k1=getchar();
}
scanf("nd\n");
while(num)
{
if(num&1)
{
memcpy(p4,p3,sizeof(p3));
memset(p3,0,sizeof(p3));
for(i=1;i<=3;++i)
for(j=1;j<=3;++j)
for(k=1;k<=3;++k)
p3[i][j]+=p4[i][k]*p2[k][j];
}
num>>=1;
memset(p4,0,sizeof(p4));
for (i=1;i<=3;++i)
for (j=1;j<=3;++j)
for (k=1;k<=3;++k)
p4[i][j]+=p2[i][k]*p2[k][j];
memcpy(p2,p4,sizeof(p4));
}
memcpy(pcdy,p3,sizeof(p3));
}
int main()
{
freopen("transform.in","r",stdin);
freopen("transform.out","w",stdout);
scanf("%d\n",&n);
int i,j,m;
double dx,dy,sx,sy,x0,y0,an,an2;
for (i=1;i<=n;++i)
scanf("%lf%lf\n",&x[i],&y[i]);
for(i=1;i<=3;++i) p[i][i]=1;
char k=getchar();
while(k=='T'||k=='S'||k=='R'||k=='L')
{
if(k=='T')
{
scanf("rans(%lf,%lf)\n",&dx,&dy);
memset(now,0,sizeof(now));
for(i=1;i<=3;++i) now[i][i]=1;
now[3][1]=dx;now[3][2]=dy;
time(3);
}
if(k=='S')
{
scanf("cale(%lf,%lf)\n",&sx,&sy);
memset(now,0,sizeof(now));
now[1][1]=sx;now[2][2]=sy;now[3][3]=1;
time(3);
}
if(k=='R')
{
scanf("otate(%lf,%lf,%lf)\n",&an,&x0,&y0);
memset(now,0,sizeof(now));
an2=(-an)*Pi/180;
now[1][1]=cos(an2);now[1][2]=sin(an2);
now[2][1]=-sin(an2);now[2][2]=cos(an2);
now[3][1]=x0+y0*sin(an2)-x0*cos(an2);
now[3][2]=y0-x0*sin(an2)-y0*cos(an2);now[3][3]=1;
time(3);
}
if(k=='L')
{
scanf("oop(%d)\n",&m);
memset(now,0,sizeof(now));
dfs(m);
memcpy(now,pcdy,sizeof(pcdy));
time(3);
}
k=getchar();
}
for(k=1;k<=n;++k)
{
ans[1]=x[k];
ans[2]=y[k];
ans[3]=1;
memset(ans2,0,sizeof(ans2));
for (i=1;i<=3;++i)
for (j=1;j<=3;++j)
ans2[i]+=ans[j]*p[j][i];
memcpy(ans,ans2,sizeof(ans2));
printf("%.4lf %.4lf\n",ans[1],ans[2]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: