1 条题解

  • 0

    题意分析

    本题模拟了泰坦尼克号历史事件中冰山警告的场景,要求计算船只与冰山之间的球面距离,并在距离小于100英里时发出危险警告。具体分析如下:

    1. 输入理解:输入包含一条格式化消息,包含船只和冰山的经纬度坐标,格式为度分秒(如414600" NL41^46'00" \ NL表示北纬41度46分0秒)。

    2. 坐标转换:需要将度分秒格式的坐标转换为十进制度数,并根据南北纬、东西经调整符号(北纬/东经为正,南纬/西经为负)。

    3. 距离计算:在球面上计算两点间的最短距离(大圆距离),使用给定的地球直径(68756875英里)。

    4. 输出要求:精确到两位小数输出距离,并在距离小于100英里时额外输出"DANGER!"。

    解题思路

    1. 解析输入:按行读取输入,提取船只和冰山的经纬度信息,包括度、分、秒和方向。

    2. 坐标转换

      • 将度分秒转换为十进制度数(例如:41°4600=41+46/60+0/360041.7667°41°46'00'' = 41 + 46/60 + 0/3600 \approx 41.7667°)。
      • 根据方向调整符号(南纬/西经为负)。
    3. 球面距离计算

      • 将十进制角度转换为弧度。
      • 使用球面余弦定理或Haversine公式计算距离: distance=Rc distance=R⋅c 其中R=68752R = \frac{6875}{2}是地球半径,cc是两点间的角距离
    4. 结果输出:格式化输出距离,并根据条件判断是否输出警告。

    实现步骤

    1. 输入解析

      • 使用字符串处理函数逐行读取并提取关键信息(如scanfscanfgetlinegetline)。
      • 解析度分秒和方向符号。
    2. 坐标转换函数

      • 实现度分秒到十进制的转换函数。
      • 根据方向调整符号。
    3. 角度转弧度:将所有角度转换为弧度用于三角函数计算。

    4. 距离计算:实现Haversine公式,计算球面距离。

    5. 输出格式化

      • 使用fixedfixedsetprecision(2)setprecision(2)确保两位小数。
      • 判断距离是否小于100英里并输出警告。

    关键代码片段(C++)

    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <cmath>
    using namespace std;
    
    const double PI = 3.14159265358979323846;
    const double EARTH_DIAMETER = 6875.0; // 地球直径(英里)
    
    // 将度分秒转换为十进制度数
    double convert_to_decimal(int degrees, int minutes, int seconds) {
        return degrees + minutes / 60.0 + seconds / 3600.0;
    }
    
    // 将角度转换为弧度
    double to_radians(double degrees) {
        return degrees * PI / 180.0;
    }
    
    int main() {
        string line;
        int message_num;
        
        // 读取消息编号
        cin.ignore(1000, '#');
        cin >> message_num;
        cin.ignore(1000, '\n');
        
        // 读取接收时间(忽略)
        getline(cin, line);
        
        // 读取"Current ship's coordinates are"
        getline(cin, line);
        
        // 读取船只纬度
        int ship_lat_deg, ship_lat_min, ship_lat_sec;
        char lat_dir;
        cin >> ship_lat_deg;
        cin.ignore(1, '^');
        cin >> ship_lat_min;
        cin.ignore(1, '\'');
        cin >> ship_lat_sec;
        cin.ignore(2, ' ');
        cin >> lat_dir;
        cin.ignore(1); // 忽略换行符
        
        // 读取船只经度
        int ship_lon_deg, ship_lon_min, ship_lon_sec;
        char lon_dir;
        cin.ignore(5); // 忽略"and "
        cin >> ship_lon_deg;
        cin.ignore(1, '^');
        cin >> ship_lon_min;
        cin.ignore(1, '\'');
        cin >> ship_lon_sec;
        cin.ignore(2, ' ');
        cin >> lon_dir;
        cin.ignore(2); // 忽略".\n"
        
        // 读取"An iceberg was noticed at"
        getline(cin, line);
        
        // 读取冰山纬度
        int ice_lat_deg, ice_lat_min, ice_lat_sec;
        char ice_lat_dir;
        cin >> ice_lat_deg;
        cin.ignore(1, '^');
        cin >> ice_lat_min;
        cin.ignore(1, '\'');
        cin >> ice_lat_sec;
        cin.ignore(2, ' ');
        cin >> ice_lat_dir;
        cin.ignore(1); // 忽略换行符
        
        // 读取冰山经度
        int ice_lon_deg, ice_lon_min, ice_lon_sec;
        char ice_lon_dir;
        cin.ignore(5); // 忽略"and "
        cin >> ice_lon_deg;
        cin.ignore(1, '^');
        cin >> ice_lon_min;
        cin.ignore(1, '\'');
        cin >> ice_lon_sec;
        cin.ignore(2, ' ');
        cin >> ice_lon_dir;
        cin.ignore(2); // 忽略".\n"
        
        // 读取"==="
        getline(cin, line);
        
        // 转换为十进制度数
        double ship_lat = convert_to_decimal(ship_lat_deg, ship_lat_min, ship_lat_sec);
        if (lat_dir == 'S') ship_lat = -ship_lat;
        
        double ship_lon = convert_to_decimal(ship_lon_deg, ship_lon_min, ship_lon_sec);
        if (lon_dir == 'W') ship_lon = -ship_lon;
        
        double ice_lat = convert_to_decimal(ice_lat_deg, ice_lat_min, ice_lat_sec);
        if (ice_lat_dir == 'S') ice_lat = -ice_lat;
        
        double ice_lon = convert_to_decimal(ice_lon_deg, ice_lon_min, ice_lon_sec);
        if (ice_lon_dir == 'W') ice_lon = -ice_lon;
        
        // 转换为弧度
        ship_lat = to_radians(ship_lat);
        ship_lon = to_radians(ship_lon);
        ice_lat = to_radians(ice_lat);
        ice_lon = to_radians(ice_lon);
        
        // 计算球面距离
        double delta_lon = ice_lon - ship_lon;
        double delta_lat = ice_lat - ship_lat;
        
        double a = pow(sin(delta_lat/2), 2) + 
                   cos(ship_lat) * cos(ice_lat) * pow(sin(delta_lon/2), 2);
        double c = 2 * atan2(sqrt(a), sqrt(1-a));
        double distance = EARTH_DIAMETER / 2 * c;
        
        // 输出结果
        cout << fixed << setprecision(2);
        cout << "The distance to the iceberg: " << distance << " miles." << endl;
        if (distance < 100.0) {
            cout << "DANGER!" << endl;
        }
        
        return 0;
    }    
    
    • 1

    信息

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