Python-CSP 201803-2 碰撞的小球
文章目录
- 一、题目
- 二、算法思想
- 三、代码
一、题目



二、算法思想
- 使用一个
列表lis来保存小球的初始位置- 用一个
列表direct来保存小球的移动方向,移动方向向右时对应的值为1,移动方向向左时对应的值为-1。- 对于某个小球来说,发生方向的变化有两种情况:一是碰到另外的一个小球,二是碰到了边界。
对于碰到边界又可以细分为两种:
- 一种是位于最右侧的小球,此时小球的位置大小就和
线段长度L相等;- 另一种是位于最左侧的小球,此时小球的位置为
0
- 对于中间部分的小球,若其中有一对小球发生碰撞,此时这两个小球的位置一定是相同的,
- 这个时候就需要让这两个小球变化方向,即左侧小球往左,右侧小球往右,然后再进行小球的移动。
- 而同一个时间,发生碰撞的小球可能会有多对。
先定义了三个函数
move、check_attack和change_direct,move函数根据小球的移动方向来移动小球;check_attack函数根据小球的位置判断是否发生了碰撞;change_direct函数是在小球发生碰撞的情况下变更碰撞小球的移动方向。
- 在函数
move(lis,direct)中,对传入的列表lis进行遍历- 如果
第i个元素的direct列表值为1时就向右移动这个小球- 否则就向左移动这个小球,遍历结束后返回
列表lis

- 在
函数check_attack(lis)中,定义一个集合set1- 因为集合类型中不能存在相同的值,所以这个
集合set1相当于对列表lis去重的结果。- 又小球发生碰撞时,
列表lis中至少会有两个元素值相同- 所以判断碰撞的条件就是看
列表lis和集合set1的元素个数是否相同。

- 在
函数change_direct(lis,direct)中,需要判断三种小球的碰撞情况- 第一种是位于最左侧的小球与线段左边界发生碰撞;
- 第二种是位于最右侧的小球与线段右边界发生碰撞;
- 第三种是位于小球之间发生碰撞。
- 由于小球的位置不一定是递增或递减排列的
- 所以此时需要使用
min()函数先确定中最靠左小球的位置- 再使用
index方法确定这个小球对应的索引。- 所以
lis.index(min(lis))就是最左侧小球的下标,而lis.index(max(lis))是最右侧小球的下标。- 如果这两种情况发生时,就分别改变对应的小球方向
- 由于
1表示向右,-1表示向左,所以向右和向左的转换只需要乘上-1即可。
- 如果是小球之间发生碰撞时,使用双循环对
列表lis进行二次遍历- 如果第
i个数等于第j个数,且i!=j,且i时就表示这两个小球发生了碰撞 - 需要
i的原因是双重遍历时会对同一对碰撞的小球进行二次操作 (二次操作相当于两个碰撞小球的方向都没有发生改变),而我们只需要第一次操作并对这两个小球进行方向的变化即可。

- 在主函数中先将数据存入
列表lis中- 此时
列表lis中元素的类型为str,所以需要进行一下int类型的转换- 在转换的同时可以初始化每个小球的方向
- 之后就是遍历
t次以表示经过了t秒- 使用
change_direct来改变发生碰撞小球的方向并返回变更后的方向列表direct- 方向改变结束就根据变化后的方向来移动小球
- 遍历
t次结束后·输出结果。
三、代码

# coding=utf-8
# 作者:小狐狸
# 题目:碰撞的小球
def move(lis,direct):'''移动小球,返回移动后的列表lis为小球列表direct为小球的方向列表'''for i in range(len(lis)):if direct[i]==1:lis[i] += 1else:lis[i] -= 1return lis
def check_attack(lis):'''发生碰撞时返回True否则返回False'''set1 = set(lis)if len(set1)==len(lis):return Falseelse:return True
def change_direct(lis,direct):'''当小球间发生碰撞或小球遇到边界时,变更碰撞小球的方向'''if lis[lis.index(min(lis))]==0: #最左侧的小球发生碰撞时direct[lis.index(min(lis))] *= -1if lis[lis.index(max(lis))]==L: #最右侧的小球发生碰撞时direct[lis.index(max(lis))] *= -1if check_attack(lis): #中间有小球发生碰撞时for i in range(len(lis)):for j in range(len(lis)):if lis[i]==lis[j] and i!=j and i<j: #若两个小球位置相同,不为同一个小球,只操作一次## print(i,j)direct[i] *= -1direct[j] *= -1 breakreturn direct
if __name__ == '__main__':n,L,t = input().split()direct = [] #各个小球移动的方向n = int(n)L = int(L)t = int(t)lis = list(input().split())for i in range(len(lis)): #转换类型为intlis[i] = int(lis[i])direct.append(1) #初始化所有小球方向
## print(lis)
## print(direct)for i in range(1,t+1): #t秒的过程direct = change_direct(lis,direct)
## print(lis,direct)lis = move(lis,direct)print(' '.join(str(i) for i in lis))
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
