【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]); } }
相关文章推荐
- [jzoj]3498. 【NOIP2013模拟联考14】图形变换(transform) (计算几何+矩阵乘法)
- 【NOIP2013模拟联考14】图形变换(transform)
- JZOJ 3498【NOIP2013模拟联考14】图形变换
- JZOJsenior3488.【NOIP2013模拟联考11】矩形(rect)
- 【NOIP2013模拟联考12】数数(数位dp||类欧几里得)
- JZOJ3455. 【NOIP2013模拟联考3】库特的向量(code)
- 【NOIP2013模拟联考5】军训(training) 题解
- JZOJ 3447【NOIP2013模拟联考2】摘取作物
- 【NOIP2013模拟联考3】恭介的法则(rule) (Standard IO)
- jzoj. 3450. 【NOIP2013模拟联考3】山峰(summits)
- 【NOIP2013模拟联考3】山峰(summits)
- [jzoj]3472. 【NOIP2013模拟联考8】匹配(match)(AC自动机+DP)
- 【NOIP2013模拟联考15】人类基因组(genes)
- JZOJ 3468. 【NOIP2013模拟联考7】OSU!(osu)
- 【NOIP2013模拟联考3】恭介的法则(rule)
- 【NOIP2013模拟联考7】数列
- 【NOIP2013模拟联考2】摘取作物(pick)
- 3472. 【NOIP2013模拟联考8】匹配(match)
- jzoj3501 【NOIP2013模拟联考15】消息传递(news) 树形dp
- 【JZOJ 3492】【NOIP2013模拟联考12】数数(count)