1 条题解
-
0
题意分析
本题模拟了泰坦尼克号历史事件中冰山警告的场景,要求计算船只与冰山之间的球面距离,并在距离小于100英里时发出危险警告。具体分析如下:
-
输入理解:输入包含一条格式化消息,包含船只和冰山的经纬度坐标,格式为度分秒(如表示北纬41度46分0秒)。
-
坐标转换:需要将度分秒格式的坐标转换为十进制度数,并根据南北纬、东西经调整符号(北纬/东经为正,南纬/西经为负)。
-
距离计算:在球面上计算两点间的最短距离(大圆距离),使用给定的地球直径(英里)。
-
输出要求:精确到两位小数输出距离,并在距离小于100英里时额外输出"DANGER!"。
解题思路
-
解析输入:按行读取输入,提取船只和冰山的经纬度信息,包括度、分、秒和方向。
-
坐标转换:
- 将度分秒转换为十进制度数(例如:)。
- 根据方向调整符号(南纬/西经为负)。
-
球面距离计算:
- 将十进制角度转换为弧度。
- 使用球面余弦定理或Haversine公式计算距离: 其中是地球半径,是两点间的角距离
-
结果输出:格式化输出距离,并根据条件判断是否输出警告。
实现步骤
-
输入解析:
- 使用字符串处理函数逐行读取并提取关键信息(如或)。
- 解析度分秒和方向符号。
-
坐标转换函数:
- 实现度分秒到十进制的转换函数。
- 根据方向调整符号。
-
角度转弧度:将所有角度转换为弧度用于三角函数计算。
-
距离计算:实现Haversine公式,计算球面距离。
-
输出格式化:
- 使用和确保两位小数。
- 判断距离是否小于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
- 上传者