CCF2018-3-18第二題 小球碰撞(假設小球之間無碰撞實現)
數軸上有一條長度為L(L為偶數)的線段,左端點在原點,右端點在座標L處。有n個不計體積的小球線上段上,開始時所有的小球都處在偶數座標上,速度方向向右,速度大小為1單位長度每秒。
當小球到達線段的端點(左端點或右端點)的時候,會立即向相反的方向移動,速度大小仍然為原來大小。
當兩個小球撞到一起的時候,兩個小球會分別向與自己原來移動的方向相反的方向,以原來的速度大小繼續移動。
現在,告訴你線段的長度L,小球數量n,以及n個小球的初始位置,請你計算t秒之後,各個小球的位置。
提示
因為所有小球的初始位置都為偶數,而且線段的長度為偶數,可以證明,不會有三個小球同時相撞,小球到達線段端點以及小球之間的碰撞時刻均為整數。
同時也可以證明兩個小球發生碰撞的位置一定是整數(但不一定是偶數)。
輸入格式
輸入的第一行包含三個整數n, L, t,用空格分隔,分別表示小球的個數、線段長度和你需要計算t秒之後小球的位置。
第二行包含n個整數a1, a2, …, an,用空格分隔,表示初始時刻n個小球的位置。
輸出格式
輸出一行包含n個整數,用空格分隔,第i個整數代表初始時刻位於ai的小球,在t秒之後的位置。
樣例輸入
3 10 5
4 6 8
樣例輸出
7 9 9
樣例:
樣例輸入
10 22 30
14 12 16 6 10 2 8 20 18 4
樣例輸出
6 6 8 2 4 0 4 12 10 2
資料規模和約定
對於所有評測用例,1 ≤ n ≤ 100,1 ≤ t ≤ 100,2 ≤ L ≤ 1000,0 < ai < L。L為偶數。
保證所有小球的初始位置互不相同且均為偶數。
問題分析
①在此問題中,假設我們將a1~an共n個球以不同位置放入,並保證第ai+1個球在第ai個球的右側,可以發現無論過程中發生怎樣的碰撞,最終運動後小球的相對位置關係不會發生變化。如果從左向右以1~n排列,那麼原本從左往右第i個小球最終也只會在第i位。
②其次小球碰撞後朝相反方向運動,可以看作小球並沒有發生碰撞,代替了令一個球的位置。兩個小球碰撞最終可以看作兩個小球各自運動最後交換。多個小球碰撞按照原從左到右順序排列即可。所以可以在輸入後記錄原來小球所在位次,最後按照這個位次輸出即可。
例如:4個球原位置 4,8,6,2,則從左往右次序為2,4,3,1。最後的輸出也得滿足該排序。
③現在只需考慮小球與牆碰撞,可以發現小球的起始位置a[i],牆的長度L,運動時間t存在如下規律:
若((a[i]+t)/L)%2=0:小球最後向右運動,最終位置為(a[i]+t)%L;
若((a[i]+t)/L)%2=1:小球最後向左運動,最終位置為L-(a[i]+t)%L。
得到各小球的位置後只需按原排列輸出即可。
程式碼如下
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX_N 100
#define MAX_L 1000
#define MAX_T 100
int main(){
int n,L,t;
int i,j,a[MAX_N],b[MAX_N],SORT_A[MAX_N]; //陣列a用於排序,陣列b記錄原輸入,SORT_A陣列用於記錄原小球所處位次
cin>>n>>L>>t;
for(i=0;i<n;i++){
cin>>a[i];
}
for(i=0;i<n;i++){
b[i]=a[i];
}
sort(a,a+n);
j=n-1;
while(j>=0){
for(i=0;i<n;i++){//按從左向右排列
if(a[j]==b[i]){
SORT_A[i]=n-j;
break;
}
}
j--;
}
for(i=0;i<n;i++){
int flag=((a[i]+t)/L)%2;//用於分析小球最後的運動狀態,flag=0向右,flag=1向左
if(0==flag) a[i]=(a[i]+t)%L;
else if(1==flag) a[i]=L-(a[i]+t)%L;
}
sort(a,a+n);//最終運動後的位置排序
for(i=0;i<n;i++){
cout<<a[n-SORT_A[i]]<<" ";//按照原有次序輸出
}
return 0;
}
第一次寫,有需要改進的希望大家提出。