1 条题解

  • 0
    @ 2025-4-8 21:05:50

    题解

    涉及知识点

    1. 运动学计算
      • 子弹与目标的相对运动轨迹
      • 碰撞检测:判断子弹是否穿过目标网格
    2. 坐标系转换
      • 将目标中心设为原点(子弹初始位置为 (0,10,H2)(0, -10, \frac{H}{2}) 米,HH 为目标高度)
    3. 网格处理
      • 将目标字符网格映射为二维坐标系

    解法代码(C++)

    #include <iostream>
    #include <vector>
    #include <cmath>
    #include <cstdio>  // 添加以使用scanf和getchar
    #include <cstdlib> // 添加以使用atoi
    
    struct Vector3 {
        double x, y, z;
        Vector3(double x=0, double y=0, double z=0) : x(x), y(y), z(z) {}
        Vector3 operator-(const Vector3& v) const {
            return Vector3(x - v.x, y - v.y, z - v.z);
        }
    };
    
    bool isHit(const Vector3& bulletVel, const Vector3& targetVel, const std::vector<std::string>& target) {
        Vector3 relVel = bulletVel - targetVel; // 相对速度
        if (relVel.y >= 0) return false; // 子弹未朝向目标运动
    
        double t = 10.0 / fabs(relVel.y); // 到达目标平面时间(秒)
        double hitX = relVel.x * t;      // 命中点X坐标(米)
        double hitZ = relVel.z * t;      // 命中点Z坐标(米)
    
        // 转换为网格坐标(10cm/格)
        int gridX = static_cast<int>(round(hitX * 10)) + target[0].size() / 2;
        int gridZ = static_cast<int>(round(hitZ * 10)) + target.size() / 2;
    
        // 检查是否命中有效格子
        return (gridZ >= 0 && gridZ < static_cast<int>(target.size()) &&
                gridX >= 0 && gridX < static_cast<int>(target[gridZ].size()) &&
                target[gridZ][gridX] != ' ');
    }
    
    int main() {
        std::string line;
        while (std::getline(std::cin, line), line.substr(0, 5) == "START") {
            int N = atoi(line.substr(6).c_str()); // 使用atoi替代stoi
            Vector3 targetVel;
            scanf("%lf,%lf,%lf", &targetVel.x, &targetVel.y, &targetVel.z);
            getchar(); // 消耗换行符
    
            std::vector<Vector3> bulletVels(N);
            for (int i = 0; i < N; ++i) {
                scanf("%lf,%lf,%lf", &bulletVels[i].x, &bulletVels[i].y, &bulletVels[i].z);
                getchar();
            }
    
            std::vector<std::string> target;
            while (std::getline(std::cin, line), line != "END") {
                target.push_back(line);
            }
    
            std::vector<std::string> result = target;
            bool hit = false;
            for (size_t i = 0; i < bulletVels.size(); ++i) { // 使用传统for循环
                if (isHit(bulletVels[i], targetVel, target)) {
                    hit = true;
                    // 标记命中点(需补充具体实现)
                    int gridZ = static_cast<int>(round((bulletVels[i].z - targetVel.z) * 10 / fabs(bulletVels[i].y - targetVel.y))) + target.size() / 2;
                    int gridX = static_cast<int>(round((bulletVels[i].x - targetVel.x) * 10 / fabs(bulletVels[i].y - targetVel.y))) + target[0].size() / 2;
                    if (gridZ >= 0 && gridZ < static_cast<int>(target.size()) &&
                        gridX >= 0 && gridX < static_cast<int>(target[gridZ].size())) {
                        result[gridZ][gridX] = '*';
                    }
                }
            }
    
            if (hit) {
                for (size_t i = 0; i < result.size(); ++i) { // 使用传统for循环
                    std::cout << result[i] << std::endl;
                }
            } else {
                std::cout << "Got Out Da Way!" << std::endl;
            }
            std::cout << std::endl;
        }
        return 0;
    }
    

    代码解释

    1. 三维向量处理Vector3 结构体存储速度向量,支持减法运算。
    2. 碰撞检测:计算子弹与目标的相对运动轨迹,判断是否命中目标网格。
    3. 输入输出:解析速度参数和目标图案,输出命中结果。

    关键公式

    • 相对速度:$\vec{V}_{\text{rel}} = \vec{V}_{\text{bullet}} - \vec{V}_{\text{target}}$
    • 命中时间:t=10Vrel,yt = \frac{10 \text{米}}{|V_{\text{rel},y}|}
    • 命中坐标:$$x = V_{\text{rel},x} \cdot t, \quad z = V_{\text{rel},z} \cdot t $$
    • 1

    信息

    ID
    1224
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    3
    已通过
    1
    上传者