解题思路
【思路一:暴力枚举】
-
初始化:首先,从输入中读取小球的数量
n
、线段的长度L
以及需要模拟的时间t
。然后,读取每个小球的初始位置,并初始化它们的移动方向为向右(用布尔值des
表示,true
表示向右,false
表示向左)。 -
模拟过程:模拟每一秒小球的运动和碰撞处理。对于每一秒,对每个小球执行以下操作:
-
移动:根据小球的移动方向更新其位置。如果
des
为true
(即向右移动),则位置x
增加1;如果des
为false
(即向左移动),则位置x
减少1。 -
碰撞检测:检查每个小球是否与线段的端点碰撞或者与其他小球碰撞。
- 与端点碰撞:如果小球位置
x
等于0(左端点)或L
(右端点),则小球改变方向(即des
取反)。 - 与其他小球碰撞:通过两层循环,比较每对小球的位置。如果有两个小球的位置相同,则这两个小球都改变方向(即各自的
des
取反)。
- 与端点碰撞:如果小球位置
-
-
输出结果:在模拟了
t
秒后,输出每个小球的最终位置。按照它们在输入时的顺序,使用空格分隔输出每个小球的位置。
这种方法直接模拟了每一秒小球的运动状态和相互之间的碰撞效果,利用了碰撞前后速度大小不变且方向相反的物理性质。通过不断更新小球的位置和方向,最终得到t
秒后各小球的位置。这种方法虽然直观,但是在小球数量较多且模拟时间较长时,效率可能不是很高,因为每一秒都要检查每个小球与其他所有小球的关系,时间复杂度较高。
【思路二:优化思路】
-
增加了索引:每个小球结构体
ball
增加了一个index
字段,用于记录小球的初始顺序。这样,无论小球如何移动和碰撞,都可以在最后按照初始顺序输出它们的位置。 -
排序优化碰撞检测:在处理小球碰撞的函数
collisonDetect
中,首先对小球按照它们的位置进行排序(使用cmp1
比较函数)。这样做的目的是将空间上相邻的小球排列在一起,以便快速检测和处理碰撞。排序后,小球如果在同一位置,则意味着它们发生了碰撞,可以直接处理相邻的小球而不需要再进行复杂的双重循环检测。 -
处理边界和碰撞:通过排序后的小球列表,代码首先检测小球是否与线段的端点碰撞(位置为
0
或L
),然后检测是否有相邻的小球在同一位置(即发生碰撞)。对于这两种情况,小球的移动方向(des
字段)都会发生改变。这种处理方式减少了不必要的比较,因为已经通过排序确保了空间上相邻的小球会被连续处理。 -
时间的模拟:与原始方法相同,代码模拟了
t
秒的时间,每一秒中所有小球根据它们的方向移动一个单位,然后调用collisonDetect
函数处理可能发生的碰撞。 -
恢复初始顺序并输出:在模拟完成后,使用
cmp2
比较函数按照小球的初始索引顺序(index
字段)将它们排序,以确保输出的顺序与题目要求的初始顺序一致。
这种优化方法通过减少碰撞检测中的比较次数和利用排序简化碰撞处理,提高了程序的效率。尽管对于每一秒的模拟依然需要遍历所有小球进行位置更新和碰撞检测,排序操作增加了额外的计算,但整体上这种方法相比于暴力检测所有小球间可能的碰撞,能够更高效地处理小球的运动和碰撞。
完整代码
【思路一:暴力枚举】
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <stack>
#include <string>
using namespace std;
struct ball
{
int x;
bool des; // 0-left 1-right
};
int n, L, t;
void collisonDetect(vector<ball> &t)
{
for (size_t i = 0; i < t.size(); i++)
{
if (t[i].x == 0 || t[i].x == L)
{
t[i].des = !t[i].des;
}
for (size_t j = i + 1; j < t.size(); j++)
{
if (t[i].x == t[j].x)
{
t[i].des = !t[i].des;
t[j].des = !t[j].des;
}
}
}
}
int main()
{
cin >> n >> L >> t;
vector<ball> list(n);
for (size_t i = 0; i < n; i++)
{
cin >> list[i].x;
list[i].des = 1; // init right
}
for (size_t i = 0; i < t; i++)
{
for (auto &it : list)
{
if (it.des) // right
it.x++;
else // left
it.x--;
}
collisonDetect(list);
}
for (auto &it : list)
{
cout << it.x << " ";
}
return 0;
}
【思路二:优化思路】
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <stack>
#include <string>
using namespace std;
struct ball
{
int x, index;
bool des; // 0-left 1-right
};
int n, L, t;
bool cmp1(ball &a, ball &b)
{
return a.x < b.x;
}
bool cmp2(ball &a, ball &b)
{
return a.index < b.index;
}
void collisonDetect(vector<ball> &t)
{
sort(t.begin(), t.end(), cmp1);
for (size_t i = 0; i < t.size(); i++)
{
if (t[i].x == 0 || t[i].x == L)
{
t[i].des = !t[i].des;
}
}
for (size_t i = 0; i < t.size() - 1; i++)
{
if (t[i].x == t[i + 1].x)
{
t[i].des = !t[i].des;
t[i + 1].des = !t[i + 1].des;
}
}
}
int main()
{
cin >> n >> L >> t;
vector<ball> list(n);
for (size_t i = 0; i < n; i++)
{
cin >> list[i].x;
list[i].des = 1; // init right
list[i].index = i + 1; // init index
}
for (size_t i = 0; i < t; i++)
{
for (auto &it : list)
{
if (it.des) // right
it.x++;
else // left
it.x--;
}
collisonDetect(list);
}
sort(list.begin(), list.end(), cmp2);
for (auto &it : list)
{
cout << it.x << " ";
}
return 0;
}