2011 ACM/ICPC 北京赛区现场赛解题:ALetter to Programmers

来源:互联网 发布:怎样做淘宝客赚钱 编辑:程序博客网 时间:2024/05/16 18:50

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4087


题目和裸的一道题,当时貌似我们也带了矩阵操作的模板,不过因为卡A和B所以没做,今天抽出了时间做了一下。


矩阵三种操作:


平移

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


一个trick,就是正常写法会出现-0.0这个解,必须手动修改偏差.....

我的代码太丑了....粘R叔的吧。

代码:

#include <iostream>#include <cctype>#include <cstdio>#include <cstring>#include <stack>#include <cmath>#define rep(i, j, k) for (int (i) = (j); (i) < (k); ++(i))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;}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 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);    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("");    }    return 0;}