1 条题解
-
0
#include <iostream> #include <vector> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> using namespace std; const double eps = 1e-6; const int SECONDS_PER_DAY = 86400; // 将时间字符串转换为秒数 int str_to_seconds(const string& s) { int h, m, sec; sscanf(s.c_str(), "%d:%d:%d", &h, &m, &sec); return h * 3600 + m * 60 + sec; } // 比较两个路径的字典序 bool greater_path(const vector<int>& a, const vector<int>& b) { for (int i = 0; i < a.size() && i < b.size(); i++) { if (a[i] != b[i]) { return a[i] > b[i]; } } return false; // 相等 } // 检查从码头i到码头j在第day天是否可行 bool check_feasible(int day, int i, int j, const vector<double>& dists, const vector<int>& inaccess, double speed, int sunrise0, int sunrise_interval, int sunset0, int sunset_interval, int tide0, int tide_interval) { // 计算第day天的日出和日落时间(相对当天00:00:00) double sunrise_d = (sunrise0 + (day - 1) * (double)sunrise_interval); sunrise_d = fmod(sunrise_d, SECONDS_PER_DAY); if (sunrise_d < 0) sunrise_d += SECONDS_PER_DAY; double sunset_d = (sunset0 + (day - 1) * (double)sunset_interval); sunset_d = fmod(sunset_d, SECONDS_PER_DAY); if (sunset_d < 0) sunset_d += SECONDS_PER_DAY; // 计算第day天的低潮事件(相对当天00:00:00) vector<double> tides; double start_abs = (day - 1) * (double)SECONDS_PER_DAY; double end_abs = day * (double)SECONDS_PER_DAY; // 计算k的范围 double k_min = ceil((start_abs - tide0) / tide_interval); if (k_min < 0) k_min = 0; double k_max = floor((end_abs - tide0 - 1) / tide_interval); for (int k = k_min; k <= k_max; k++) { double t_abs = tide0 + k * (double)tide_interval; if (t_abs >= start_abs && t_abs < end_abs) { double t_rel = t_abs - start_abs; tides.push_back(t_rel); } } // 计算码头i的不可达区间(在[日出,日落]内) double w_i = inaccess[i] * 3600.0; vector<pair<double, double> > intervals; for (int idx = 0; idx < tides.size(); idx++) { double t_tide = tides[idx]; double L = max(sunrise_d, t_tide - w_i); double R = min(sunset_d, t_tide + w_i); if (L <= R + eps) { intervals.push_back(make_pair(L, R)); } } // 合并重叠的区间 vector<pair<double, double> > merged; if (!intervals.empty()) { sort(intervals.begin(), intervals.end()); double L = intervals[0].first, R = intervals[0].second; for (int idx = 1; idx < intervals.size(); idx++) { if (intervals[idx].first <= R + eps) { R = max(R, intervals[idx].second); } else { merged.push_back(make_pair(L, R)); L = intervals[idx].first; R = intervals[idx].second; } } merged.push_back(make_pair(L, R)); } // 计算最早出发时间 double current = sunrise_d; double depart_time = -1; for (int idx = 0; idx < merged.size(); idx++) { double L = merged[idx].first, R = merged[idx].second; if (current + eps < L) { depart_time = current; break; } else { if (current < R + eps) { current = R + eps; } } } if (depart_time < 0) { if (current < sunset_d + eps) { depart_time = current; } else { return false; } } if (depart_time > sunset_d + eps) { return false; } // 计算划行时间(秒) double time_paddle = (dists[j] - dists[i]) / speed * 3600.0; double t_arrive = depart_time + time_paddle; if (t_arrive > sunset_d + eps) { return false; } // 检查到达码头j时是否可达 double w_j = inaccess[j] * 3600.0; for (int idx = 0; idx < tides.size(); idx++) { double t_tide = tides[idx]; double low_start = t_tide - w_j; double low_end = t_tide + w_j; if (t_arrive >= low_start - eps && t_arrive <= low_end + eps) { return false; } } return true; } int main() { int max_days; while (cin >> max_days) { if (max_days == 0) break; double speed; cin >> speed; string sunrise_str, sunrise_interval_str; cin >> sunrise_str >> sunrise_interval_str; int sunrise0 = str_to_seconds(sunrise_str); int sunrise_interval = str_to_seconds(sunrise_interval_str); string sunset_str, sunset_interval_str; cin >> sunset_str >> sunset_interval_str; int sunset0 = str_to_seconds(sunset_str); int sunset_interval = str_to_seconds(sunset_interval_str); string tide_str, tide_interval_str; cin >> tide_str >> tide_interval_str; int tide0 = str_to_seconds(tide_str); int tide_interval = str_to_seconds(tide_interval_str); int n_docks; cin >> n_docks; int n = n_docks + 1; // 总点数(包括起点0和终点) vector<double> dists(n); vector<int> inaccess(n); for (int i = 0; i < n; i++) { cin >> dists[i] >> inaccess[i]; } // 动态规划数组:dp[d][i]存储第d天到达码头i的路径序列 vector<vector<vector<int> > > dp(max_days + 1, vector<vector<int> >(n)); dp[0][0] = vector<int>(1, 0); // 第0天在起点0 int min_days = -1; vector<int> final_path; for (int d = 1; d <= max_days; d++) { for (int i = 0; i < n; i++) { if (dp[d - 1][i].empty()) continue; // 尝试到达更远的码头j(从远到近尝试) for (int j = n - 1; j > i; j--) { if (check_feasible(d, i, j, dists, inaccess, speed, sunrise0, sunrise_interval, sunset0, sunset_interval, tide0, tide_interval)) { vector<int> candidate = dp[d - 1][i]; candidate.push_back(j); // 如果dp[d][j]为空或当前路径更优 if (dp[d][j].empty() || greater_path(candidate, dp[d][j])) { dp[d][j] = candidate; } } } } // 如果到达终点,记录最小天数 if (!dp[d][n - 1].empty()) { min_days = d; final_path = dp[d][n - 1]; break; } } if (min_days == -1) { cout << "NO ITINERARY POSSIBLE" << endl; } else { // 输出从第1天到第min_days天的停靠码头 for (int i = 1; i <= min_days; i++) { if (i > 1) cout << " "; cout << final_path[i]; } cout << endl; } } return 0; }
- 1
信息
- ID
- 588
- 时间
- 1000ms
- 内存
- 10MiB
- 难度
- 9
- 标签
- 递交数
- 1
- 已通过
- 0
- 上传者