CSP-202309-2-坐标变换(其二)

一、遇到问题:迭代计算时间超限

  • 按照常规思路,可以从beginend逐步计算,共需要约end-begin次运算,时间复杂度较高,导致时间超限。

二、解决思路:累积

1.操作数累积部分

在输入阶段,代码通过循环读取每个操作,根据操作类型(1或2)更新累积的缩放系数和旋转角度。

  • 对于缩放操作(flag为1),将当前操作数的缩放系数k更新为前一步操作数的缩放系数乘以当前操作的数值num。同时,保持旋转角度r不变。

  • 对于旋转操作(flag为2),将当前操作数的旋转角度r更新为前一步操作数的旋转角度加上当前操作的数值num。同时,保持缩放系数k不变。

这样,通过不断累积操作数,数组x中保存了每一步的累积结果

2. 查询阶段

对于每个查询,代码读取起始和结束位置,以及初始点的坐标。然后,根据累积的操作数,计算起始和结束位置的缩放系数和旋转角度。最后,对初始点进行一次相应的缩放和旋转计算,得到最终结果。

double k1 = x[end].k / x[begin - 1].k;
double r1 = x[end].r - x[begin - 1].r;
x1 *= k1, y1 *= k1;
double temp_x1 = x1, temp_y1 = y1;
x1 = temp_x1 * cos(r1) - temp_y1 * sin(r1);
y1 = temp_x1 * sin(r1) + temp_y1 * cos(r1);

3.总结

上述思路可以优化时间复杂度的主要原因在于通过累积操作数的方式,避免了直接迭代计算。下面是具体的优化原因:

  1. 累积操作数减少迭代次数: 传统的计算方式是逐步迭代,每一步都重新计算累积的缩放系数和旋转角度,时间复杂度为O(N)。而在优化的思路中,通过累积操作数,每一步都是在前一步的基础上进行更新。为操作直接提供了最终状态,而不是通过逐步计算得到。

  2. 常数时间的查询操作: 在查询阶段,通过累积操作数,可以直接计算起始和结束位置的缩放系数和旋转角度,而不需要进行迭代计算。这使得查询操作的时间复杂度为常数时间,而不是线性时间。

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
struct Operand
{
    double k;
    double r;
};

int main() {
    int numberOfOperations, numberOfQueries;
    cin >> numberOfOperations >> numberOfQueries;
    Operand* x = new Operand[numberOfOperations + 1];
    for (int i = 0; i <= numberOfOperations; i++)
    {
        x[i] = { 1,0 };
    }
    
    // 输入操作数(累积)
    for (int i = 1; i <= numberOfOperations; i++)
    {
        int flag;
        double num;
        cin >> flag >> num;
        // k
        if (flag == 1)
        {
            x[i].k = x[i - 1].k * num;
            x[i].r = x[i - 1].r;
        }
        // r
        if (flag == 2)
        {
            x[i].k = x[i - 1].k;
            x[i].r = x[i - 1].r + num;
        }
    }

    // 输入查询
    for (int i = 0; i < numberOfQueries; i++)
    {
        int begin, end;
        double x1, y1;
        cin >> begin >> end >> x1 >> y1;
        double k1 = x[end].k / x[begin - 1].k;
        double r1 = x[end].r - x[begin - 1].r;

        x1 *= k1, y1 *= k1;

        double temp_x1 = x1, temp_y1 = y1;
        x1 = temp_x1 * cos(r1) - temp_y1 * sin(r1);
        y1 = temp_x1 * sin(r1) + temp_y1 * cos(r1);

        cout << fixed << setprecision(3) << x1 << " " << y1 << endl;
    }
    return 0;
}

请添加图片描述

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值