老王的自动驾驶决策和规划第一章

news2024/12/23 4:59:57

文章目录

  • 自动驾驶决策规划算法
    • 序章
    • 第一章
      • (1) 细说五次多项式
      • (2) 凸优化与非凸优化
      • (3) 直角坐标与自然坐标转换(上, 下)

自动驾驶决策规划算法

序章

课程链接:序章

第一章

(1) 细说五次多项式

课程链接:五次多项式

参考一下这篇博客:

初始:位置,速度,加速度

终点:位置,速度,加速度。

边界条件就是六个初始条件,t = 0 时刻的,和t = t0的时刻状态,就可以求解这个五次多项式,得到一个x轴位置,速度, 加速度关于t的方程。和y轴位置,速度,和加速度关于t的方程。

比较简单,只需要代入公式即可。

设一个五次多项式,分别对应的是x(t), y(t), v_x(t), v_y(t), a_x(t), a_y(t)

值得注意的一点是:五次多项式做轨迹规划,y不是关于x的曲线,而是y和x都是关于t的曲线。
请添加图片描述

写为矩阵形势就是:

请添加图片描述

目前我们已知的信息是t0时刻的位置、速度和加速度。以及T终点时刻的根据这个初始t = 0的条件, 代入方程,可以求出a0,a1, 和a2.

然后根据T时刻的位置,速度和加速度,代入方程中,可以求得剩下的a3,a4,a5.具体计算如下所示,(这里用横向求解来举例,纵向也是一样的过程)

t = 0的时刻,将初始条件代入方程得到的是:
x ( t 0 ) = x ( 0 )    =    x s = a 0    x ′ ( t 0 )    =    v s    =    a 1 x ′ ′ ( t 0 )    =    a s    =    2 ∗ a 2 x\left( t_0 \right) =x\left( 0 \right) \,\,=\,\,x_s=a_0\,\, \\ x\prime\left( t_0 \right) \,\,=\,\,v_s\,\,=\,\,a_1 \\ x''\left( t_0 \right) \,\,=\,\,a_s\,\,=\,\,2*a_2 x(t0)=x(0)=xs=a0x(t0)=vs=a1x′′(t0)=as=2a2
这样可以求得三个方程组中的参数。然后是对T时刻的求解,将终点时刻的已知量代入到函数中,由于a0,a1,a2都是已知的了,我们将其移到左边,只构建右边a3,a4,a5三个未知量的矩阵来求解,首先代入后公式如下:
x ( t T ) = x ( T )    =    x g    −    a 0    − a 1 T    −    a 2 T =    a 3 T 3    +    a 4 T 4    +    a 5 T 5 x ′ ( t T )    =    v g − a 1 − 2 a 2 T    =    3 a 3 T 2 + 4 a 4 T 3 + 5 a 5 T 4 x ′ ′ ( t T )    =    a g − 2 ∗ a 2    =    6 a 3 T    +    12 a 4 T 2 + 20 a 5 T 3 x\left( t_T \right) =x\left( T \right) \,\,=\,\,x_g\,\,-\,\,a_0\,\,-a_1T\,\,-\,\,a_2T=\,\,a_3T^3\,\,+\,\,a_4T^4\,\,+\,\,a_5T^5 \\ x\prime\left( t_T \right) \,\,=\,\,v_g-a_1-2a_2T\,\,=\,\,3a_3T^2+4a_4T^3+5a_5T^4 \\ x''\left( t_T \right) \,\,=\,\,a_g-2*a_2\,\,=\,\,6a_3T\,\,+\,\,12a_4T^2+20a_5T^3 x(tT)=x(T)=xga0a1Ta2T=a3T3+a4T4+a5T5x(tT)=vga12a2T=3a3T2+4a4T3+5a5T4x′′(tT)=ag2a2=6a3T+12a4T2+20a5T3
利用python自带的np求解工具就可以求得剩余的a参数。写成矩阵形式很简单。

下面结合代码来写一下五次多项式的类。

# ########################################
# 构造一个五次多项式的类
class QuinticPolynomial:
    def __init__(self, xs, vxs, axs, xe, vxe, axe, time):
        # 起点条件代入进去得
        self.a0 = xs
        self.a1 = vxs
        self.a2 = axs / 2.0
        # 终点条件代入进去
        A = np.array([[time ** 3, time**4, time ** 5],
                      [3*time**2, 4*time**3, 5*time**4],
                      [6*time, 12*time**2, 20*time**3]])
        b = np.array([xe - self.a0 - self.a1*time - self.a2*time**2,
                      vxe - self.a1 - 2*self.a2*time,
                      axe - 2*self.a2])
        x = np.linalg.solve(A, b)
        self.a3 = x[0]
        self.a4 = x[1]
        self.a5 = x[2]

    def calc_point(self, t):  # 计算下一时刻t的位置。
        xt = self.a0 + self.a1 * t + self.a2 * t**2 + self.a3*t**3 + \
             self.a4 * t**4 + self.a5*t**5
        return xt

    def calc_first_derivative(self, t):  # 计算速度
        xt = self.a1 + 2* self.a2*t + 3*self.a3*t**2 + 4*self.a4*t**3 + 5*self.a5**4
        return xt

    def calc_second_derivative(self, t):  # 计算加速度
        xt = 2*self.a2 + 6*self.a3*t + 12*self.a4*t**2 + 20*self.a5*t**3
        return xt

    def calc_third_derivative(self, t):  # 返回jerk
        xt = 6*self.a3 + 24*self.a4*t + 60*self.a5*t**2
        return xt

完整代码如下:、

# 首先是输入的参数
import math
import matplotlib.pyplot as plt
import numpy as np
# ###########################################输入参数
MAX_T = 100.0  # 到达目标所需要的最大时间
MIN_T = 5.0  # 到达目标的最小时间

# 起点条件
sx = 10.0
sy = 10.0
syaw = np.deg2rad(10.0)
sv = 1.0
sa = 0.1

# 终点条件
gx = 30.0
gy = -10.0
gyaw = np.deg2rad(20.0)  # 终点的偏航角
gv = 1.0
ga = 0.1  # 加速度 m/ss

# 设置一个最大加速度与jerk
max_accel = 1.0
max_jerk = 0.5

# 时间间隔
dt = 0.1
# ########################################
# 构造一个五次多项式的类
class QuinticPolynomial:
    def __init__(self, xs, vxs, axs, xe, vxe, axe, time):
        # 起点条件代入进去得
        self.a0 = xs
        self.a1 = vxs
        self.a2 = axs / 2.0
        # 终点条件代入进去
        A = np.array([[time ** 3, time**4, time ** 5],
                      [3*time**2, 4*time**3, 5*time**4],
                      [6*time, 12*time**2, 20*time**3]])
        b = np.array([xe - self.a0 - self.a1*time - self.a2*time**2,
                      vxe - self.a1 - 2*self.a2*time,
                      axe - 2*self.a2])
        x = np.linalg.solve(A, b)
        self.a3 = x[0]
        self.a4 = x[1]
        self.a5 = x[2]

    def calc_point(self, t):  # 计算下一时刻t的位置。
        xt = self.a0 + self.a1 * t + self.a2 * t**2 + self.a3*t**3 + \
             self.a4 * t**4 + self.a5*t**5
        return xt

    def calc_first_derivative(self, t):  # 计算速度
        xt = self.a1 + 2* self.a2*t + 3*self.a3*t**2 + 4*self.a4*t**3 + 5*self.a5**4
        return xt

    def calc_second_derivative(self, t):  # 计算加速度
        xt = 2*self.a2 + 6*self.a3*t + 12*self.a4*t**2 + 20*self.a5*t**3
        return xt

    def calc_third_derivative(self, t):  # 返回jerk
        xt = 6*self.a3 + 24*self.a4*t + 60*self.a5*t**2
        return xt


# #######################################
# 构造五次多项式
# 计算出时间、空间、速度、加速度和jerk的信息

def quintic_polynomials_planner(sx, sy, syaw, sv, sa, gx, gy, gyaw, gv, ga, max_accel, max_jerk, dt):
    """
    :param sx:
    :param sy:
    :param syaw:
    :param sv:
    :param sa:
    :param gx:
    :param gy:
    :param gyaw:
    :param gv:
    :param ga:
    :param max_accel:
    :param max_jerk:
    :param dt:
    :return: time: time result
    rx : x position result list
    ry : y position result list
    ryaw : yaw angle result list
    rv: velocity result list
    ra: accel result list
    """
    # 将起点和终点速度进行横纵向解耦 注意:s代表起始位置,g代表目标位置
    vxs = sv * math.cos(syaw)
    vys = sv * math.sin(syaw)
    vxg = gv * math.cos(gyaw)
    vyg = gv * math.sin(gyaw)

    # 加速度解耦
    axs = sa * math.cos(syaw)
    ays = sa * math.sin(syaw)
    axg = ga * math.cos(gyaw)
    ayg = ga * math.sin(gyaw)

    # 创建一个计算求得的参考信息列表:
    time, rx, ry, ryaw, rv, ra, rj = [], [], [], [], [], [], []
    # np.arrange(a, b, c)有三个参数的时候,a是起点,b是终点,c是代表步长,生成一个列表
    # MINT是5,计算未来5个时间步的数据。
    # 枚举不同时间,生成对应的多项式轨迹。
    for T in np.arange(MIN_T, MAX_T, MIN_T): # 从最短的时间到最长的时间
        xqp = QuinticPolynomial(sx, vxs, axs, gx, vxg, axg, T)  # 横向五次多项式类对象
        yqp = QuinticPolynomial(sy, vys, ays, gy, vyg, ayg, T)  # 纵向
        time, rx, ry, ryaw, rv, ra, rj = [], [], [], [], [], [], []
        for t in np.arange(0.0, T+dt, dt):  # 枚举时间步长
            time.append(t)
            rx.append(xqp.calc_point(t))
            ry.append(yqp.calc_point(t))

            vx = xqp.calc_first_derivative(t)
            vy = yqp.calc_first_derivative(t)  # 未来dt时刻的坐标
            v = np.hypot(vx, vy)
            # v就是将vx和vy进行合成
            rv.append(v)

            yaw = math.atan2(vy, vx)
            ryaw.append(yaw)

            ax = xqp.calc_second_derivative(t)
            ay = yqp.calc_second_derivative(t)
            a = np.hypot(ax, ay)
            if len(rv) >=2 and rv[-1] - rv[-2] < 0.0:  # 如果速度开始下降,这里加速度需要取反。
                a *= -1
            # 说明在减速
            ra.append(a)

            jx = xqp.calc_third_derivative(t)  # 计算jerk
            jy = yqp.calc_third_derivative(t)  # 计算y方向的
            j = np.hypot(jx, jy)
            if len(ra) >= 2 and ra[-1] - ra[-2] < 0.0:  # 将加速度开始下降,jerk需要取反
                j *= -1
            rj.append(j)
        if max([abs(i) for i in ra]) <= max_accel and max([abs(i) for i in rj]) <= max_jerk:
            print("find path!!")
            break
    return time, rx, ry, ryaw, rv, ra, rj


time, rx, ry, ryaw, rv, ra, rj = quintic_polynomials_planner(
        sx, sy, syaw, sv, sa, gx, gy, gyaw, gv, ga, max_accel, max_jerk, dt)

# 绘制路径图
plt.subplots(1)
plt.plot(sx, sy, "or", label="Start")
plt.plot(gx, gy, "ob", label="Goal")
plt.plot(rx, ry, "-k", label="Path")
plt.grid(True)
plt.axis("equal")
plt.xlabel("x[m]")
plt.ylabel("y[m]")
plt.legend()

# 绘制速度曲线
plt.subplots(1)
plt.plot(time, rv, "-r", label="velocity")
plt.grid(True)
plt.xlabel("Time [s]")
plt.ylabel("Velocity [m/s]")
plt.legend()

plt.show()

(2) 凸优化与非凸优化

课程链接:优化

大纲:

本节主要引出了参考线,还有约束问题,其次是代价。

首先来回顾一下规划总体流程:(已经得到了导航路径,需要决策 + 运动规划)


  1. 定位和导航: 生成 参考线坐标
  2. 分情况
    • 无障碍物: 跟踪参考线路径
    • 有静态障碍物: 静态障碍物投影到SL图上(Frenet)
  3. 决策算法:对障碍物进行决策,决定是 左避,还有右避,或者忽略。(开辟最优凸空间)
  4. 规划算法: 在凸空间中搜索出来最优的路径。
  5. 后续处理:在规划轨迹中选取一个点,坐标转化为笛卡尔坐标系,输出给控制模块去控制即可。

从上述流程可以了解到 首先需要解决的是参考线问题。接下来讲解一下参考线。

参考线:

目标:

  • 解决导航的路径过长,不平滑的问题,通常从导航中获取到的全局路径都是由一段一段的线段构成,比较粗略,因此需要利用参考线实现平滑的操作。

  • 路径太长,不方便找匹配点,搜索空间太大,也就是不利于坐标变换。

实现方案:每一个规划周期中,找到车在导航路径上的投影点,然后以投影点为坐标原点,往后取30米长度,往前取150米范围内的点,来做平滑,平滑后的点的集合称之为参考线。

具体实现:平滑算法。

利用三个点来找平滑的关系,然后简历一个二次规划来找到一个最优解。计算平滑代价,找到最小的。

(3) 直角坐标与自然坐标转换(上, 下)

课程链接:坐标变换1, 坐标变换2

这一节内容主要看这三个博客:

第一节

第二节

第三节

具体内容如下:

通过第一节的计算,我们得出来一个Cartesian坐标系转化到Frenet坐标系的步骤:

请添加图片描述

对应的python代码如下:

import numpy as np
from math import *

# 本函数是将Cartesian坐标系,转化为Frenet坐标系
# rs是参考点的frenet坐标纵向位置
# 已知(x_x,y_x,theta_x, v_x, a_x, k_x) 和 参考点(s_r, x_r, y_r, theta_r, v_r, a_r, k_r, d_kr)
# 待求:(六个参数) s, s_dot, s_dot_dot, l, l_pie, l_pie_pie.
def cartesian_to_frenet1D(rs, rx, ry, rtheta, rkappa, rdkappa, x, y, v, a, theta, kappa):
    # 创建一个numpy数组, 长度为3,初始值为0. s代表纵向的三个参数,位置,速度,加速度。 d代表横向三个参数
    s_condition = np.zeros(3)
    d_condition = np.zeros(3)

    dx = x - rx
    dy = y - ry

    cos_theta_r = cos(rtheta)
    sin_theta_r = sin(rtheta)

    cross_rd_nd = cos_theta_r*dy - sin_theta_r*dx  # 计算第二步,朝向C参数
    s_condition[0] = rs  # s
    # 第三步
    d_condition[0] = copysign(sqrt(dx*dx+dy*dy), cross_rd_nd)  # copysign(x, y)返回一个基于x绝对值和基于y符号的数值。x * y
    # 第四步
    delta_theta = theta - rtheta  # 角度差
    tan_delta_theta = tan(delta_theta)
    cos_delta_theta = cos(delta_theta)
    one_minis_kappa_r_d = 1 - rkappa * d_condition[0]  # C_drdx参数, 上面计算的d_condition[0]是横向误差d,也就是l
    # 第五步
    d_condition[1] = one_minis_kappa_r_d * tan_delta_theta
    # 第六步
    kappa_r_d_prime = rdkappa * d_condition[0] + rkappa * d_condition[1]
    # 第七步:计算l_pie_pie
    d_condition[2] = (-kappa_r_d_prime) * tan_delta_theta + one_minis_kappa_r_d / cos_delta_theta / cos_delta_theta *\
                     (kappa*one_minis_kappa_r_d / cos_delta_theta - rkappa)

    # 第八步:计算纵向位置s
    s_condition[0] = rs
    # 第九步:s_dot
    s_condition[1] = v * cos_delta_theta / one_minis_kappa_r_d
    # 第十步:计算参数C_dtheta
    delta_theta_prime = one_minis_kappa_r_d / kappa / cos_delta_theta - rkappa
    # 第十一步:计算s_dot_dot
    s_condition[2] = (a * cos_delta_theta - s_condition[1]* s_condition[1] * (d_condition[1] * delta_theta_prime - kappa_r_d_prime)) / (one_minis_kappa_r_d)

    return s_condition, d_condition


接下来是对Frenet坐标系转化为全局坐标系

请添加图片描述

代码如下:

def frenet_to_cartesian(rs, rx, ry, rtheta, rkappa, rdkappa, s_condition, d_condition):
    if fabs(rs - s_condition[0]) >= 1.0e-6:
        print("The reference point s and s_condition[0] don't match.")  # 说明参考点距离车辆太远了。
    cos_theta_r = cos(rtheta)
    sin_theta_r = sin(rtheta)
    # 第一步和第二步:计算x,y坐标
    x = rx - d_condition[0] * sin_theta_r
    y = ry + d_condition[0] * cos_theta_r
    # 中间参数
    one_minus_kappa_r_d  = 1 - rkappa*d_condition[0]
    tan_delta_theta = d_condition[1] / one_minus_kappa_r_d
    # 第四步计算角度
    delta_theta = atan2(tan_delta_theta, one_minus_kappa_r_d)  # d_theta
    theta = NormalizeAngle(delta_theta + rtheta)
    # 第五步:计算速度
    d_dot = d_condition[1] * s_condition[1]
    v = sqrt(one_minus_kappa_r_d * one_minus_kappa_r_d * s_condition[1]*s_condition[1] + d_dot * d_dot)
    # 第六步,计算角度
    cos_delta_theta = cos(delta_theta)
    # 第七步,计算C_kr_l参数
    kappa_r_d_prime = rdkappa * d_condition[0] + rkappa * d_condition[1]
    # 第八步:计算kx
    kappa = ((d_condition[2] + kappa_r_d_prime*tan_delta_theta) * cos_delta_theta * cos_delta_theta/one_minus_kappa_r_d + rkappa) \
            * cos_delta_theta / one_minus_kappa_r_d

    # 第九步:计算a
    a = s_condition[2] * (one_minus_kappa_r_d / cos_delta_theta) + (s_condition[1] * s_condition[1] / cos_delta_theta)* \
        (d_condition[1] * (kappa*one_minus_kappa_r_d/cos_delta_theta - rkappa) - kappa_r_d_prime)

    return x, y, v, a, theta, kappa

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/482109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于SpringBoot整合Websocket实现简易对话聊天窗

前言 官网链接&#xff1a;Websocket Websocket 是什么&#xff1f;它可以将两个独立的浏览器窗口作为通信的两端。 这种形式的通信与传统的 HTTP、TCP 所不同。传统的 HTTP 请求—响应协议是无法实现实时通信的&#xff0c;也就是说&#xff0c;只能由客户端向服务端发送请求…

前端Web开发,HTML,css,JavaScript

web浏览器响应流程&#xff0c;及技术不同的浏览器&#xff0c;内核不同&#xff0c;对于相同的前端代码解析的效果会存在差异web标准&#xff0c;三个组成部分 HTML&#xff1a;负责网页的结构&#xff08;页面元素和内容&#xff09;CSS&#xff1a;负责页面的表现&#xff0…

VC调试方法大全

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

代码随想录算法训练营第四十八天| 198.打家劫舍、213.打家劫舍II、337.打家劫舍III

文章目录 198.打家劫舍213.打家劫舍II337.打家劫舍III 198.打家劫舍 题目链接&#xff1a;代码随想录 解题思路&#xff1a; 1.dp[i]&#xff1a;考虑下标i&#xff08;包括i&#xff09;以内的房屋&#xff0c;最多可以偷窃的金额为dp[i] 只是考虑&#xff0c;不一定偷 2.递推…

【STM32CubeMX】F103外部中断

前言 本文记录下我学习STM32CubeMX时的流程&#xff0c;方便以后回忆。系统板是基于STM32F103C6T6。本章记录外部中断。 步骤 该实验步骤以&#xff0c;配置PA1为外部中断下降沿触发事件&#xff0c;在触发事件后点亮板载PC13LED灯 时钟配置和生成文件配置之类的&#xff0c;其…

3.6 cache存储器

学习步骤&#xff1a; 我会采取以下几个步骤来学习Cache存储器&#xff1a; 确定学习目标&#xff1a;Cache存储器作为一种高速缓存存储器&#xff0c;通常用于提高计算机系统的运行效率。因此&#xff0c;我需要明确学习Cache存储器的目的&#xff0c;包括了解其原理、结构和…

No.054<软考>《(高项)备考大全》【冲刺8】《软考之 119个工具 (6)》

《软考之 119个工具 &#xff08;6&#xff09;》 99.应急应对策略:100.风险在评估:101.风险审计:102.偏差和趋势分析:103.技术绩效测量:104.自制或外购分析:105.市场调研:106.投标人会议:107.建议书评价技术:108.独立核算:109.广告:110.采购谈判:111.合同变更控制系统:112.采购…

定位图像坐标系和角度误区

坐标系和角度的常见误区 在学习halcon的时候.常常看文档的时候,会有一些地方比较疑感有些常用的地方有细微的差距,一不留意。就会导致计算的数据出错 常见的误区就在坐标系和角度 halcon的帮助情况 存在Px,Py 大家不要被搞混乱 Px -> Row Py-> Column 很多人定位项…

C语言——字符串及字符函数的介绍

C语言——字符串及字符函数的介绍 一、字符函数1.strlen1.1strlen的使用1.2strlen的三种模拟实现1.2.1计数器实现strlen函数1.2.2递归方法实现strlen函数1.2.3指针方法实现strlen函数 1.3 注意事项 2.strcpy2.1strcpy使用2.2strcpy的模拟实现2.3strcpy的注意事项 3.strcat3.1st…

【小样本分割 2022 ECCV】SSP

文章目录 【小样本分割 2022 ECCV】SSP摘要1. 介绍2. 相关工作3. 自支持小样本语义分割3.1 动机3.2 自支持原型-SSM3.3 自适应自支持背景原型-ASBP3.4 自支持匹配-SSL 3. 代码 【小样本分割 2022 ECCV】SSP 论文题目&#xff1a;Self-Support Few-Shot Semantic Segmentation 中…

SpringCloud 微服务系列——【Gateway、Config组件使用】

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

第二十三章 材质

3D模型主要是通过材质&#xff08;Material&#xff09;和贴图&#xff08;Texture&#xff09;来表现其精美的外表&#xff0c;说白了就是一张“画皮”而已。我们之前的DirectX课程中介绍过材质&#xff0c;它实际就是对光的反射率&#xff0c;这样简单的设置并不能展现3D模型…

Linux线程 概念、特点、线程间资源共享情况

1. 线程概念 线程是轻量级的进程&#xff1b;Linux中&#xff0c;线程本质上仍是进程。 进程是OS分配资源的最小单位&#xff0c;线程是OS调度的最小单位。 NPTL 当前Linux线程库为redHat开发的NPTL&#xff0c;查看本地线程库版本&#xff1a; getconf GNU_LIBPTHREAD_VE…

【C++】三元操作符、创建并初始化C++对象、C++new关键字

C的三元操作符 if的语法糖 例1 #include <iostream> #include <string>static int s_Level 1; static int s_Speed 2;int main() {if (s_Level > 5){s_Speed 10;}else{s_Speed 5;}std::cin.get(); }用三元操作符&#xff1a; s_Speed s_Level > 5 ?…

基础篇-并发篇

**63.线程状态 添加主线程和子线程 ** 65.线程状态 核心线程和任务队列都是有上限的&#xff0c;所以都满了话就开始使用救急线程; 救急线程也是有上限的&#xff0c;如果再来新的线程的话就需要拒绝策越; 注意&#xff1a;这里不需要等待5000ms&#xff0c;几乎是同时打印 注…

[230503] 2021年托福阅读真题第1篇|Grinding Grain 磨粒

11:21&#xff5e;11:41 慢 20min 正确率&#xff1a;6.5/10 题目来源&#xff1a;链接: https://pan.baidu.com/s/15FYCuD7__slfGvdsBIHgLQ 提取码: iynj --来自百度网盘超级会员v5的分享【内含2021年100篇托福阅读真题】 目录 Grinding Grain 题目 Grinding Grain It now…

2016 ICPC合肥站 传递 HDU-5961(拓扑排序 / bitset / 暴力(可hack))

题目链接&#xff1a;HDU-5961 传递 中文题面就不解释题目意思&#xff0c;解释一下名词的意思 完全图&#xff1a;对于一个无向图 G G G 而言&#xff0c;设点集为 V V V&#xff0c;点集中任意不相同两点 u , v u, v u,v 间都有且仅有一条边叫做完全图。 竞赛图&#xff1…

【玩转Git三剑客笔记】第一章 Git基础

第一章 Git基础 1.综述2.安装Git3.使用Git之前需要做的最小配置4.创建第一个仓库并配置local用户信息1.创建Git仓库2.设置Git最小配置 5.通过几次commit来认识工作区和暂存区1.将工作区中所有已经被git追踪的文件一起添加到暂存区2.git log查看提交日志 6.给文件重命名的简便方…

密码学【java语言】初探究

文章目录 前言一 密码学1.1 古典密码学1.1.1 替换法1.1.2 移位法1.1.3 古典密码破解方式 二 近代密码学2.1 现代密码学2.1.1 散列函数2.1.2 对称密码2.1.3 非对称密码 二 凯撒加密的实践2.1 基础知识&#xff1a;ASCII编码2.2 ascii编码演示2.3 凯撒加密和解密实践2.4 频率分析…

安装Ubuntu22.04虚拟机的一些常见问题解决方法

文章目录 VirttalBox 开启共享剪切板文件夹、拖放的功能VirtualBox 安装 ubuntu后安装增强工具无效的解决办法解决ubuntu您没有权限查看“ 某某文件夹”的内容所需的权限linux更换源的两种方法[如何在 Ubuntu 20.04 上安装 Visual Studio Code - ](https://zhuanlan.zhihu.com/…