洛谷P1007题 解题思路和步骤 C++实现带注释 洛谷出题
洛谷P1007题是算法竞赛中的经典模拟问题,要求计算两支队伍通过独木桥的最长时间。本文将从问题分析、数学模型建立到C++代码实现,详细讲解如何通过双向队列模拟和相遇处理机制解决该问题,并提供带完整注释的代码示例。
问题分析与建模
本题的核心在于模拟两队人马在桥上的相遇过程。初始状态下,两队分别位于桥的两端,每个士兵的移动速度为1单位/秒。当两队士兵在桥中间相遇时,需要按照题目规则处理他们的移动方向。我们需要建立数学模型:将桥抽象为长度为L的直线坐标系,两队初始位置分别为0和L+1。使用双向队列(deque)存储每个士兵的位置信息,可以高效处理前进方向的变化。
相遇判断与处理机制
如何处理两队士兵的相遇情况是本问题的关键。当左队士兵和右队士兵的位置坐标相邻时,即满足pos_left +1 == pos_right的条件,就会发生相遇。此时需要比较两士兵到达相遇点的时间:如果左队士兵先到达,则右队士兵需要等待;反之亦然。这里的时间计算需要考虑士兵的移动速度和初始位置,建立时间戳跟踪每个士兵的移动轨迹。
模拟算法设计
采用双队列同步推进的算法结构,左队列和右队列分别存储对应方向的士兵位置。每次循环处理三个步骤:1. 移动所有士兵位置 2. 检测相遇情况 3. 处理边界条件。在C++实现中,可以使用deque容器来高效实现队列的两端操作。时间变量从0开始递增,直到所有士兵都通过桥的另一端。如何优化循环终止条件?需要持续跟踪两队队列的剩余人数。
数据结构与代码实现
以下是带详细注释的C++实现代码。我们使用结构体存储每个士兵的信息,包括当前位置和所属队伍。双队列分别管理左右两个方向的士兵,时间戳变量记录全局时间。核心处理逻辑集中在移动士兵和检测相遇两个函数模块,时间复杂度为O(N+M),适用于题目给定的数据范围。
#include#includeusing namespace std; struct Soldier { int pos; // 当前位置 int team; // 所属队伍(0左/1右) }; int main() { int L, N, M; cin >> L >> N >> M; dequeleft, right; // 初始化左队士兵 for(int i=0; i0, 0}); // 初始化右队士兵 for(int i=0; i1, 1}); int time = 0; while(!left.empty() || !right.empty()) { // 移动左队士兵 for(auto& s : left) s.pos++; // 移动右队士兵 for(auto& s : right) s.pos--; // 检测相遇情况 auto l = left.begin(); auto r = right.begin(); while(l != left.end() && r != right.end()) { if(l->pos == r->pos) { // 相遇处理逻辑 if(time % 2 == 0) right.erase(right.begin()); else left.erase(left.begin()); } ++l; ++r; } // 处理到达终点的士兵 while(!left.empty() && left.front().pos > L) left.pop_front(); while(!right.empty() && right.front().pos < 1) right.pop_front(); time++; } cout << time-1 << endl; // 减去一轮无效移动 return 0; }
测试用例与优化建议
为确保代码正确性,需要测试边界情况。当L=1时两队士兵在中间点相遇的情况。测试用例1:L=4,N=1,M=1,正确输出应为5。优化方向包括使用更高效的数据结构,或者预先计算相遇时间。但考虑到题目数据范围(N,M ≤ 1000),当前实现已满足时间要求。
通过本文的详细分析,我们完整呈现了洛谷P1007题的解题思路和C++实现。关键在于正确建立士兵移动模型,处理相遇时的等待逻辑。代码中使用的双向队列和结构体封装,既保证了算法效率又增强了可读性。掌握这种模拟类问题的解法,对提升算法竞赛能力至关重要。
原创内容 转载请注明出处