HDU 4087 & BOJ 244 A Letter to Programmers 【三维仿射变幻的齐次矩阵乘+快速幂】

HDU 4087 & BOJ 244 A Letter to Programmers 【三维仿射变幻的齐次矩阵乘+快速幂】

题意很裸,亮点在于将齐次仿射变换矩阵和快速幂结合起来。

题目读入延续了pku出题的ws风格,还得用一个dfs处理读入。
题目输出也很蛋疼,标准写法竟然会导致-0.0出现,必须手动加一个eps来修改偏差。没有spj的二货。

附上仿射变换矩阵:

平移
translate tx ty tz
1 0 0 tx
0 1 0 ty
0 0 1 tz
0 0 0 1
缩放
scale kx ky kz
kx 0  0  0
0  ky 0  0
0  0  kz 0
0  0  0  1
绕任意轴(过原点)旋转(注意要把轴向量归一化,不然会在“点在轴上”这个情况下出问题)
rotate x y z d
(1-cos(d))*x*x+cos(d)     (1-cos(d))*x*y-sin(d)*z   (1-cos(d))*x*z+sin(d)*y   0
(1-cos(d))*y*x+sin(d)*z   (1-cos(d))*y*y+cos(d)     (1-cos(d))*y*z-sin(d)*x   0
(1-cos(d))*z*x-sin(d)*y   (1-cos(d))*z*y+sin(d)*x   (1-cos(d))*z*z+cos(d)     0
          0                          0                           0            1

附代码,一开始装b用stack模拟读入过程,re啊wa啊各种sb。最后被迫用了dfs。唉,naive。


#include <iostream>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <stack>
#include <cmath>
using  namespace std;
const  double eps = 1e-6;
const  double pi = acos(-1.0);
const  int maxn = 1005;
int sgn( double x){ return x < -eps?-1:x > eps;}
#define rep(i,j,k) for(int (i) = (j);(i) < (k);(i) ++)
struct matrix
{
     int r,c;
     double v[5][5];
    matrix(){}
    matrix( int a, int b):r(a),c(b)
    {
        rep(i,0,r)
            fill(v[i],v[i] + c,0.0);
         if(r == c)
        {
            rep(i,0,r)
                v[i][i] = 1.0;
        }
    }
    matrix init()
    {
         return matrix(r,c); 
    }
    matrix  operator * ( const matrix p)
    {
        matrix ans(r,p.c);
        rep(i,0,r)
            rep(j,0,ans.c)
            {
                 double tmp = 0.0;
                rep(k,0,c)
                    tmp += v[i][k] * p.v[k][j];
                ans.v[i][j] = tmp;
            }
         return ans;
    }
};
matrix power(matrix a, int n)
{
    matrix e(a.c,a.c); // square matrix of a.c * a.c
     if(n == 0)
         return e;
    matrix ans = power(a,n/2);
    ans = ans * ans;
     return (n%2)?ans * a : ans;
}
struct point
{
     double x,y,z;
    point(){}
    point( double a, double b, double c):x(a),y(b),z(c){}
     void  in()
    {
        scanf("%lf %lf %lf",&x,&y,&z);
    }
     void print()
    {
        printf("%.2lf %.2lf %.2lf\n",x + eps,y + eps,z + eps);
    }
}p[maxn];
int n;
point fuck(point now,matrix a)
{
    matrix o(4,1);
    o.v[0][0] = now.x;
    o.v[1][0] = now.y;
    o.v[2][0] = now.z;
    o.v[3][0] = 1.0;
    matrix ans = a * o;
     return point(ans.v[0][0],ans.v[1][0],ans.v[2][0]);
}
char op[20];
matrix dfs( int times)
{
    matrix ans(4,4);
     double v[5];
     int what;
     while(scanf("%s",op) == 1)
    {
        matrix temp(4,4);
         if(op[0] == 'e')
             break;
         else  if(op[0] == 'r')
        {
             if(op[1] == 'e')
            {
                scanf("%d",&what);
                temp = dfs(what);
            }
             else
            {
                rep(i,0,4)
                    scanf("%lf",&v[i]);
                 double l = 0.0;
                rep(i,0,3)
                    l += v[i] * v[i];
                l = sqrt(l);
                v[3] = v[3] / 180.0 * pi;
                 double ct = cos(v[3]),st = sin(v[3]);
                rep(i,0,3)
                    v[i] /= l;
                temp.v[0][0] = (1.0 - ct) * v[0] * v[0] + ct;
                temp.v[0][1] = (1.0 - ct) * v[0] * v[1] - st * v[2];
                temp.v[0][2] = (1.0 - ct) * v[0] * v[2] + st * v[1];
                temp.v[1][0] = (1.0 - ct) * v[1] * v[0] + st * v[2];
                temp.v[1][1] = (1.0 - ct) * v[1] * v[1] + ct;
                temp.v[1][2] = (1.0 - ct) * v[1] * v[2] - st * v[0];
                temp.v[2][0] = (1.0 - ct) * v[2] * v[0] - st * v[1];
                temp.v[2][1] = (1.0 - ct) * v[2] * v[1] + st * v[0];
                temp.v[2][2] = (1.0 - ct) * v[2] * v[2] + ct;
            }
        }
         else  if(op[0] == 't')
        {
            rep(i,0,3)
            {
                scanf("%lf",&v[i]);
                temp.v[i][3] = v[i];
            }
        }
         else  if(op[0] == 's')
        {
            rep(i,0,3)
            {
                scanf("%lf",&v[i]);
                temp.v[i][i] = v[i];
            }
        }
        ans = temp * ans;
    }
     return power(ans,times);
}
int main()
{
     while(scanf("%d",&n) == 1 && n)
    {
        matrix temp(4,4);
        temp = dfs(1) * temp;
         for( int i = 0;i < n;i++)
        {
            p[i]. in();
            p[i] = fuck(p[i],temp);
            p[i].print();
        }
        puts("");
    }
}
Enter

你可能感兴趣的:(HDU 4087 & BOJ 244 A Letter to Programmers 【三维仿射变幻的齐次矩阵乘+快速幂】)