碰撞球游戲,CCF201803-2 碰撞的小球(100分)【模擬】

 2023-11-18 阅读 17 评论 0

摘要:試題編號:201803-2試題名稱:碰撞的小球時間限制:1.0s內存限制:256.0MB問題描述: 問題描述   數軸上有一條長度為L(L為偶數)的線段,左端點在原點,右端點在坐標L處。有n個不計體積的小球在線段上,開始時所有的
試題編號:201803-2
試題名稱:碰撞的小球
時間限制:1.0s
內存限制:256.0MB
問題描述:

問題描述

  數軸上有一條長度為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

樣例輸出

ccf2020答案?7 9 9

樣例說明

  初始時,三個小球的位置分別為4, 6, 8。

  一秒后,三個小球的位置分別為5, 7, 9。

  兩秒后,第三個小球碰到墻壁,速度反向,三個小球位置分別為6, 8, 10。

  三秒后,第二個小球與第三個小球在位置9發生碰撞,速度反向(注意碰撞位置不一定為偶數),三個小球位置分別為7, 9, 9。

  四秒后,第一個小球與第二個小球在位置8發生碰撞,速度反向,第三個小球碰到墻壁,速度反向,三個小球位置分別為8, 8, 10。

  五秒后,三個小球的位置分別為7, 9, 9。

樣例輸入

ccf第三題、10 22 30
14 12 16 6 10 2 8 20 18 4

樣例輸出

6 6 8 2 4 0 4 12 10 2

數據規模和約定

ccf2021初賽、  對于所有評測用例,1 ≤ n ≤ 100,1 ≤ t ≤ 100,2 ≤ L ≤ 1000,0 < ai < L。L為偶數。
  保證所有小球的初始位置互不相同且均為偶數。

?

問題鏈接:CCF201803-2 碰撞的小球

問題分析

小球碰撞實驗視頻,? 這是一個模擬題,按照時間序列進行模擬,模擬小球的運動過程。好在每個時間單位小球只移動一個位置,處理起來就要簡單一些。模擬題關鍵在于采用什么樣的數據表示,這里給出2種解法。

? 方法一(不排序,暴力):

? 使用數組pos[i]存儲第i個球的初始位置;使用數組step[i]存儲第i個球現在的運動方向,step[i]=1表示向右走,step[i]=-1表示往左走,用加法運算就可以實現小球的移動。

? 模擬過程是按照時間序列,先計算小球的下一個位置,如果該位置為兩端則改變運動方向。再根據小球的新位置看看有沒有2個小球碰頭,有的話分別改變運動方向。只是簡單地判斷2個小球是否碰頭需要用暴力法算一下。

小球碰撞實驗報告?? 方法二(結構數組,排序):

? 如果不想用暴力,則將有關參數放入一個結構數組中,給每一個小球編號,排序后再進行模擬,輸出結果時再按照編號重新排序即可。

程序說明:(略)

題記

質量相同兩個小球碰撞?? 沒有好辦法就暴力,沒有好辦法就模擬。這個題正好應驗了這兩句話。

?

提交后得100分的C++語言程序(方法一)如下:

/* CCF201803-2 碰撞的小球 */#include <iostream>using namespace std;const int L = 1000;
int pos[L + 1], step[L + 1];int main()
{int n, l, t;cin >> n >> l >> t;for(int i = 0; i < n; i++) {cin >> pos[i];// 開始往右走,到達兩端則回頭step[i] = 1;if(pos[i] == l || pos[i] == 0)step[i] = -step[i];}for(int i = 0; i < t; i++) {// 走一步for(int j = 0; j < n; j++) {pos[j] += step[j];// 到達兩端則回頭if(pos[j] == l || pos[j] == 0)step[j] = -step[j];}// 判斷是否碰頭,碰頭則掉頭(要避免重復比較)for(int j = 0; j < n; j++)for(int k = j + 1; k < n; k++)if(pos[k] == pos[j])step[k] = -step[k], step[j] = -step[j];}for(int i = 0; i < n; i++)cout << pos[i] << " ";cout << endl;return 0;
}

?

碰撞的小球、提交后得100分的C++語言程序(方法二)如下:

/* CCF201803-2 碰撞的小球 */#include <iostream>
#include <algorithm>using namespace std;const int N = 100;
struct Node {int id;         // 小球編號int pos;        // 位置int step;       // 運動方向,1表示向右,-1表示向左
} b[N];bool cmp1(Node a, Node b)
{return a.pos < b.pos;
}bool cmp2(Node a, Node b)
{return a.id < b.id;
}int main()
{int n, l, t, id = 0;cin >> n >> l >> t;for(int i = 0; i < n; i++) {b[i].id = ++id;cin >> b[i].pos;// 開始往右走,到達兩端則回頭b[i].step = 1;if(b[i].pos == l || b[i].pos == 0)b[i].step = -b[i].step;}sort(b, b + n, cmp1);for(int i = 0; i < t; i++) {// 走一步for(int j = 0; j < n; j++) {b[j].pos += b[j].step;// 到達兩端則回頭if(b[j].pos == l || b[j].pos == 0)b[j].step = -b[j].step;}// 判斷是否碰頭,碰頭則掉頭(排序后只需要比較相鄰的)for(int j = 1; j < n; j++)if(b[j].pos == b[j - 1].pos)b[j].step = -b[j].step, b[j - 1].step = -b[j - 1].step;}sort(b, b + n, cmp2);for(int i = 0; i < n; i++)cout << b[i].pos << " ";cout << endl;return 0;
}

?

?

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/175946.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息