碰撞的小球 201803-2 C++


一、题目

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

原题目链接

二、解题

1.题目

这段代码通过模拟小球在一维轴上的运动来解决碰撞小球问题。它读入小球的数量 n,轴的长度 L 和运动的时间 t,然后读入每个小球的初始位置并存储在数组 a 中。接下来,代码进入一个循环,循环次数为 t。在每次循环中,代码遍历所有小球,并根据每个小球的方向更新它们的位置。如果小球到达轴的端点,它会反弹并改变方向。如果两个小球相遇,它们也会改变方向。最后,代码输出每个小球在 t 个时间步长后的位置。

2.代码

dev c++ 5.11

//201803-2 碰撞的小球
#include<iostream>
using namespace std;
int a[110]; // 存储每个小球的位置
bool dir[110]; // 存储每个小球的方向
int main(){
    int n,L,t; // n: 小球数量,L: 轴长度,t: 运动时间
    cin>>n>>L>>t;
    for(int i=0;i<n;i++){
        cin>>a[i]; // 读入每个小球的初始位置
    }
    while(t--){ // 循环 t 次
        for(int i=0;i<n;i++){ // 遍历所有小球
            if(dir[i]) a[i]--; // 如果小球方向为左,位置减一
            else a[i]++; // 否则位置加一
            if(a[i]>L){ // 如果小球到达右端点
                a[i]=L-1; // 反弹
                dir[i]=!dir[i]; // 改变方向
            }
            if(a[i]<0){ // 如果小球到达左端点
                a[i]=1; // 反弹
                dir[i]=!dir[i]; // 改变方向
            }
            for(int j=0;j<i;j++){ // 检查是否与其他小球相遇
                if(a[i]==a[j]){ 
                    dir[i]=!dir[i]; // 改变方向
                    dir[j]=!dir[j];
                    break;
                }
            }
        }
    }
    for(int i=0;i<n;i++){ // 输出每个小球的最终位置
        cout<<a[i]<<" ";
    }
    return 0;
}



3.提交结果

在这里插入图片描述

总结

1.解释

这段代码的时间复杂度为 O(t*n^2),因为它需要在每个时间步长内遍历所有小球并检查它们是否相遇。如果 n 和 t 都很大,这段代码可能会运行得比较慢。

一种可能的优化方法是使用更高效的数据结构来存储小球的位置,以便快速检查它们是否相遇。例如,可以使用平衡二叉搜索树来存储小球的位置。这样,在每个时间步长内,可以在 O(log n) 的时间内找到与给定小球相邻的小球,并在 O(log n) 的时间内更新它们的位置。这样,整个算法的时间复杂度就降低到了 O(tnlog n)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的用 C++ 编写的小球碰撞模拟程序,希望对您有所帮助。 ```c++ #include <iostream> #include <cmath> using namespace std; const double PI = 3.141592653589793; class Ball { public: Ball(double x, double y, double r, double vx, double vy, double m) : x_(x), y_(y), r_(r), vx_(vx), vy_(vy), m_(m) {} double GetX() const { return x_; } double GetY() const { return y_; } double GetRadius() const { return r_; } double GetVx() const { return vx_; } double GetVy() const { return vy_; } double GetMass() const { return m_; } void SetX(double x) { x_ = x; } void SetY(double y) { y_ = y; } void SetVx(double vx) { vx_ = vx; } void SetVy(double vy) { vy_ = vy; } void Move(double dt) { x_ += vx_ * dt; y_ += vy_ * dt; } friend bool IsCollided(const Ball& b1, const Ball& b2) { double dx = b1.x_ - b2.x_; double dy = b1.y_ - b2.y_; double d = sqrt(dx * dx + dy * dy); return d <= b1.r_ + b2.r_; } friend void Collide(Ball& b1, Ball& b2) { double dx = b1.x_ - b2.x_; double dy = b1.y_ - b2.y_; double d = sqrt(dx * dx + dy * dy); if (d < 1e-6) return; // 重叠了就不碰撞了 double nx = dx / d; double ny = dy / d; double tx = -ny; double ty = nx; double v1n = b1.vx_ * nx + b1.vy_ * ny; double v1t = b1.vx_ * tx + b1.vy_ * ty; double v2n = b2.vx_ * nx + b2.vy_ * ny; double v2t = b2.vx_ * tx + b2.vy_ * ty; double v1n_ = (v1n * (b1.m_ - b2.m_) + 2 * b2.m_ * v2n) / (b1.m_ + b2.m_); double v2n_ = (v2n * (b2.m_ - b1.m_) + 2 * b1.m_ * v1n) / (b1.m_ + b2.m_); b1.vx_ = v1n_ * nx + v1t * tx; b1.vy_ = v1n_ * ny + v1t * ty; b2.vx_ = v2n_ * nx + v2t * tx; b2.vy_ = v2n_ * ny + v2t * ty; } private: double x_; // x 坐标 double y_; // y 坐标 double r_; // 半径 double vx_; // x 方向速度 double vy_; // y 方向速度 double m_; // 质量 }; int main() { double x1 = 0, y1 = 0, r1 = 1, vx1 = 1, vy1 = 0, m1 = 1; double x2 = 3, y2 = 0, r2 = 1, vx2 = -1, vy2 = 0, m2 = 1; Ball b1(x1, y1, r1, vx1, vy1, m1); Ball b2(x2, y2, r2, vx2, vy2, m2); double dt = 0.01; int steps = 1000; for (int i = 0; i < steps; ++i) { if (IsCollided(b1, b2)) { Collide(b1, b2); } b1.Move(dt); b2.Move(dt); cout << "step " << i << ": (" << b1.GetX() << ", " << b1.GetY() << "), (" << b2.GetX() << ", " << b2.GetY() << ")" << endl; } return 0; } ``` 以上代码中,我们定义了一个 `Ball` 类,表示一个小球,其中包含了小球的位置、半径、速度和质量等信息。我们还定义了两个函数 `IsCollided` 和 `Collide`,分别用于判断两个小球是否碰撞,并进行碰撞处理。在主函数中,我们创建了两个小球,并模拟它们的运动过程,输出每一步后两个小球的位置信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值