1 条题解

  • 0
    @ 2025-12-9 17:21:21

    第三部分:题目分析与标准代码

    1. 解题思路

    • 模拟过程:依次读取每条指令,更新 xxyy 的值。
    • 纬度处理
      • 纬度是“有界”的,类似于在墙角走路,撞墙就停。
      • 使用 if (x > 90) x = 90;if (x < -90) x = -90; 进行修正。
    • 经度处理
      • 经度是“循环”的,类似于在圆环上走路。
      • 向东 (E)y += val。如果 y > 180,则 y -= 360
      • 向西 (W)y -= val。如果 y <= -180,则 y += 360
      • 注意:虽然题目中 V360V \le 360,通常一次 if 就够了,但为了严谨性(防止多圈),建议使用 while 循环进行修正。

    2. 标准代码 (C++14)

    /**
     * 题目:航海家的坐标 (The Navigator's Coordinates)
     * 难度:GESP 4级
     * 知识点:模拟、边界判断、循环修正
     */
    
    #include <iostream>
    
    using namespace std;
    
    int main() {
        // 提升 IO 效率
        ios::sync_with_stdio(false);
        cin.tie(NULL);
    
        int N;
        int x, y; // x: 纬度, y: 经度
        
        // 读入 N 和初始坐标
        if (!(cin >> N >> x >> y)) return 0;
    
        for (int i = 0; i < N; ++i) {
            char dir;
            int val;
            cin >> dir >> val;
    
            if (dir == 'N') {
                x += val;
                // 纬度北界处理:不能超过 90
                if (x > 90) x = 90;
            } 
            else if (dir == 'S') {
                x -= val;
                // 纬度南界处理:不能低于 -90
                if (x < -90) x = -90;
            } 
            else if (dir == 'E') {
                y += val;
                // 经度向东跨越处理:范围 (-180, 180]
                // 如果大于 180,减去 360
                while (y > 180) {
                    y -= 360;
                }
            } 
            else if (dir == 'W') {
                y -= val;
                // 经度向西跨越处理
                // 如果小于等于 -180,加上 360
                while (y <= -180) {
                    y += 360;
                }
            }
        }
    
        cout << x << " " << y << endl;
    
        return 0;
    }
    

    第四部分:数据生成器

    这是用于生成 1.in ~ 10.in 及其对应标准答案的生成器代码。

    /**
     * GESP 4级 [航海家的坐标] - 数据生成器
     */
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <ctime>
    
    using namespace std;
    
    // ------------------------------------------
    // 标准解法函数 (生成 .out)
    // ------------------------------------------
    void solve(int N, int x, int y, const vector<pair<char, int>>& ops, ofstream& fout) {
        for (auto op : ops) {
            char dir = op.first;
            int val = op.second;
    
            if (dir == 'N') {
                x += val;
                if (x > 90) x = 90;
            } else if (dir == 'S') {
                x -= val;
                if (x < -90) x = -90;
            } else if (dir == 'E') {
                y += val;
                while (y > 180) y -= 360;
            } else if (dir == 'W') {
                y -= val;
                while (y <= -180) y += 360;
            }
        }
        fout << x << " " << y << endl;
    }
    
    // 辅助函数
    int randRange(int min, int max) {
        return rand() % (max - min + 1) + min;
    }
    
    char randDir() {
        char dirs[] = {'N', 'S', 'E', 'W'};
        return dirs[rand() % 4];
    }
    
    int main() {
        srand(time(0));
        
        cout << "Start generating data..." << endl;
    
        for (int i = 1; i <= 10; ++i) {
            string in_name = to_string(i) + ".in";
            string out_name = to_string(i) + ".out";
            ofstream fin(in_name);
            ofstream fout(out_name);
    
            int N, x0, y0;
            vector<pair<char, int>> ops;
    
            // 构造测试点
            if (i == 1) { 
                // 样例 1
                N = 3; x0 = 0; y0 = 170;
                ops = {{'E', 20}, {'N', 100}, {'E', 10}};
            }
            else if (i == 2) {
                // 样例 2
                N = 2; x0 = 0; y0 = -170;
                ops = {{'W', 20}, {'S', 100}};
            }
            else if (i == 3) { 
                // 极点阻挡测试
                N = 2; x0 = 80; y0 = 0;
                ops = {{'N', 20}, {'N', 20}}; // 应该停在 90
            }
            else if (i == 4) {
                // 日界线反复横跳
                N = 4; x0 = 0; y0 = 179;
                ops = {{'E', 2}, {'W', 2}, {'E', 2}, {'W', 2}};
            }
            else if (i == 5) {
                // 刚好 -180 边界测试
                N = 1; x0 = 0; y0 = -170;
                ops = {{'W', 10}}; // -180 -> 180
            }
            else if (i == 6) {
                // 大数值绕圈 (经度)
                N = 1; x0 = 0; y0 = 0;
                ops = {{'E', 360}}; // 应该回到 0
            }
            else if (i == 7) {
                // 混合随机小数据
                N = 10; x0 = 0; y0 = 0;
                for(int k=0; k<N; k++) ops.push_back({randDir(), randRange(1, 50)});
            }
            else if (i == 8) {
                // 纯经度移动
                N = 20; x0 = 45; y0 = 0;
                for(int k=0; k<N; k++) {
                    char d = (rand()%2) ? 'E' : 'W';
                    ops.push_back({d, randRange(10, 100)});
                }
            }
            else if (i == 9) {
                // 纯纬度移动
                N = 20; x0 = 0; y0 = 100;
                for(int k=0; k<N; k++) {
                    char d = (rand()%2) ? 'N' : 'S';
                    ops.push_back({d, randRange(10, 100)});
                }
            }
            else { 
                // 大规模随机
                N = 1000; x0 = randRange(-90, 90); y0 = randRange(-179, 180);
                for(int k=0; k<N; k++) ops.push_back({randDir(), randRange(1, 360)});
            }
    
            // 写入输入
            fin << N << " " << x0 << " " << y0 << endl;
            for(auto op : ops) {
                fin << op.first << " " << op.second << endl;
            }
    
            // 写入输出
            solve(N, x0, y0, ops, fout);
    
            fin.close();
            fout.close();
            cout << "Generated Case " << i << endl;
        }
        
        cout << "Done!" << endl;
        return 0;
    }
    
    • 1

    信息

    ID
    19276
    时间
    1000ms
    内存
    32MiB
    难度
    10
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者