试题编号: | 201803-2 |
试题名称: | 碰撞的小球 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 数轴上有一条长度为L(L为偶数)的线段,左端点在原点,右端点在坐标L处。有n个不计体积的小球在线段上,开始时所有的小球都处在偶数坐标上,速度方向向右,速度大小为1单位长度每秒。 提示 因为所有小球的初始位置都为偶数,而且线段的长度为偶数,可以证明,不会有三个小球同时相撞,小球到达线段端点以及小球之间的碰撞时刻均为整数。 输入格式 输入的第一行包含三个整数n, L, t,用空格分隔,分别表示小球的个数、线段长度和你需要计算t秒之后小球的位置。 输出格式 输出一行包含n个整数,用空格分隔,第i个整数代表初始时刻位于ai的小球,在t秒之后的位置。 样例输入 3 10 5 样例输出 7 9 9 样例说明 初始时,三个小球的位置分别为4, 6, 8。 样例输入 10 22 30 样例输出 6 6 8 2 4 0 4 12 10 2 数据规模和约定 对于所有评测用例,1 ≤ n ≤ 100,1 ≤ t ≤ 100,2 ≤ L ≤ 1000,0 < ai < L。L为偶数。 |
分析
题目已给出速度恒定为1,且题目说了不可能有3个小球同时相撞,所以处理时只需考虑邻近2个小球。小球先做位移,然后处理碰撞(即更新下一秒的前进方向)。
我们先思考小球反向的条件:
1)碰到边界(只有第一个和最后一个小球);
2)两个相邻小球碰撞(不相邻怎么碰撞o(╯□╰)o);
如此根据大概思路边完善边写代码;
代码
我们假设小球的依次在线段上从小到大排列;
其中数组 pos 为小球位置,数组 dir 为对应小球下一步运动的方向,方向:向左 = -1,向右 = 1;
特别注意:在比较相邻的小球时必须是两者都移动之后,才能进行比较并更新下一步方向;(采取前缀比较)// test.cpp: 定义控制台应用程序的入口点。 // #include<iostream> using namespace std; int pos[105]; int dir[105]; int main() { int n, L, t; cin >> n >> L >> t; for (int i = 1; i <= n; i++) { cin >> pos[i]; dir[i] = 1; //初始化方向 } for (int j = 1; j <= t; j++) { pos[1] += dir[1]; //防止下溢出,单独处理第一个球 if (pos[1] == 0) { dir[1] *= -1; } for (int i = 2; i <= n; i++) { pos[i] += dir[i]; //先位移 if (pos[i - 1] == pos[i]) //再更新下一步方向 { dir[i - 1] *= -1; dir[i] *= -1; } } if (pos[n] == L) //处理最后一个球 { dir[n] *= -1; } } for (int i = 1; i <= n; i++) { cout << pos[i] << " "; } return 0; }
但是,题目不会这样简单o(╯□╰)o;
题目给出的小球顺序和其所在位置的大小顺序是无序的;
所以改进一下上面的代码,我们创建一个结构体来封装三个变量-----位置 pos,下一步方向 dir,输入的原始顺序 index;
重构sort()中的cmp函数:变为cmpPos()与cmpIndex(),来从小到大排列;
// test.cpp: 定义控制台应用程序的入口点。 // #include<iostream> #include<algorithm> using namespace std; typedef struct Ball { int pos; int dir; int index; }; Ball ball[105]; bool cmpPos(Ball a, Ball b) { return a.pos < b.pos ; } bool cmpIndex(Ball a, Ball b) { return a.index < b.index ; } int main() { int n, L, t; cin >> n >> L >> t; for (int i = 1; i <= n; i++) { cin >> ball[i].pos; ball[i].dir = 1; ball[i].index = i; //预置输入顺序 } sort(ball, ball + n + 1, cmpPos); //按照pos大小排列 for (int j = 1; j <= t; j++) { ball[1].pos += ball[1].dir; if (ball[1].pos == 0) //防止下溢出,单独处理第一个球 { ball[1].dir *= -1; } for (int i = 2; i <= n; i++) { ball[i].pos += ball[i].dir; //先位移 if (ball[i - 1].pos == ball[i].pos) //再更新下一步的运动方向 { ball[i - 1].dir *= -1; ball[i].dir *= -1; } } if (ball[n].pos == L) //处理最后一个球 { ball[n].dir *= -1; } } sort(ball, ball + n + 1, cmpIndex); //按照原顺序排列 for (int i = 1; i <= n; i++) { cout << ball[i].pos << " "; } return 0; }
.