Python-CSP 201803-2 碰撞的小球

文章目录

  • 一、题目
  • 二、算法思想
  • 三、代码

一、题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、算法思想

  • 使用一个列表lis来保存小球的初始位置
  • 用一个列表direct来保存小球的移动方向,移动方向向右时对应的值为1,移动方向向左时对应的值为-1
  • 对于某个小球来说,发生方向的变化有两种情况:一是碰到另外的一个小球,二是碰到了边界。

对于碰到边界又可以细分为两种:

  • 一种是位于最右侧的小球,此时小球的位置大小就和线段长度L相等;
  • 另一种是位于最左侧的小球,此时小球的位置为0
  • 对于中间部分的小球,若其中有一对小球发生碰撞,此时这两个小球的位置一定是相同的,
  • 这个时候就需要让这两个小球变化方向,即左侧小球往左,右侧小球往右,然后再进行小球的移动。
  • 而同一个时间,发生碰撞的小球可能会有多对。

先定义了三个函数move、check_attack和change_directmove函数根据小球的移动方向来移动小球;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))


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章