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

题目传送门: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值