遗传算法实现的旅行商问题解决方案

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:旅行商问题(TSP)是NP完全问题,要求旅行商访问多个城市各一次并返回起点,目标是总旅行距离最短。遗传算法是解决此类问题的有效手段,通过模仿自然选择过程迭代优化种群,实现对TSP的高效求解。算法包括初始化种群、适应度评估、选择、交叉、变异和替换等关键步骤。本文档包含遗传算法的实现代码和详细注释,辅助读者深入理解并应用遗传算法求解TSP问题。
基于遗传算法的tsp问题求解,基于遗传算法的旅行商问题求解(代码完整,数据齐全)

1. 旅行商问题(TSP)简介

旅行商问题(Traveling Salesman Problem, TSP)是组合优化中的一个经典问题,它要求寻找一条最短的路径,使得旅行商从一个城市出发,经过所有城市恰好一次后,最后回到原点。这个问题不仅是组合优化领域中一个广为人知的问题,也是计算机科学与运筹学交叉研究的重要课题。

1.1 问题的定义和复杂性

TSP问题可以用图论的语言定义为:给定一个加权完全图(即图中每条边都有一个权重,代表两个城市之间的距离),寻找一个最小权重的哈密顿回路(即经过每个顶点恰好一次的闭合回路)。尽管定义简单,但TSP问题却是NP-hard(非确定性多项式时间复杂度硬问题),这意味着目前不存在能在多项式时间内解决TSP问题的已知算法。

1.2 TSP问题的实际应用

TSP问题在现实生活中有着广泛的应用,例如物流配送、电路板钻孔、DNA测序、机器人路径规划等。虽然TSP问题的完美解很难找到,但通过启发式算法,比如遗传算法,我们可以找到足够好的近似解来满足实际应用的需求。这些近似解在实际中通常能够提供足够好的路径安排,并能够有效节省成本和时间。

在后续章节中,我们将探讨一种强大的算法——遗传算法,它如何在TSP问题上发挥独特的作用,找到既有效又实用的解决方案。

2. 遗传算法原理与应用

2.1 遗传算法的基本概念

2.1.1 遗传算法的历史和发展

遗传算法(Genetic Algorithms, GAs)是一种模拟自然选择过程的搜索优化算法,由John Holland及其学生和同事们在上世纪70年代初期开发。Holland是美国密歇根大学的计算机科学与工程教授,他通过对生物进化的观察和理解,提出了模拟生物进化过程来解决优化问题的思想。

遗传算法的灵感主要来源于达尔文的自然选择理论和孟德尔的遗传学说。在自然界中,生物通过生存竞争和适者生存的方式进化出更加适应环境的特征。类似地,在算法中,通过选择、交叉(杂交)和变异等遗传操作对候选解进行处理,从而产生新的候选解群体,这个群体在适应度上更优,更接近问题的最优解。

随着理论的发展和计算能力的增强,遗传算法已经成为解决复杂优化问题的重要工具,被广泛应用于机器学习、神经网络、调度问题、人工智能等领域。随着并行计算和分布式系统的普及,遗传算法的求解规模和求解效率得到了显著提升,它在解决大规模优化问题中表现出的潜力吸引了越来越多的研究者和工程师的关注。

2.1.2 遗传算法的工作原理

遗传算法是一种迭代搜索算法,其基本工作原理类似于生物进化过程中的”适者生存”。算法从一组随机生成的候选解(称为”种群”)开始,然后通过选择、交叉和变异等遗传操作产生新的种群,不断迭代进化,直至满足停止条件。

  1. 初始化种群 :首先,算法随机生成一个初始种群,每个个体代表一个潜在的解。
  2. 评估适应度 :算法会根据适应度函数来评估每个个体对环境的适应程度,适应度高的个体被选中的机会更大。

  3. 选择 :选择过程模拟自然选择机制,通过某种选择策略(如轮盘赌选择、锦标赛选择等),从当前种群中选择较优的个体作为下一代的父母。

  4. 交叉(杂交) :通过交叉操作,父母个体可以交换基因片段产生后代,这样可以保留优良基因并生成新的基因组合。

  5. 变异 :为了维持种群的多样性,防止算法过早收敛,变异操作随机改变个体的部分基因。

  6. 迭代 :重复上述步骤,直到满足停止条件,如达到最大迭代次数或者适应度达到某个阈值。

  7. 解码最优解 :最后,算法从最终的种群中选出最优个体,其代表问题的最优解。

遗传算法的关键在于保持种群多样性,避免过早收敛到局部最优解,同时通过选择、交叉和变异操作逐步逼近全局最优解。这种算法由于其通用性和简单性,在解决优化问题时具有广泛的应用前景。

2.2 遗传算法的核心组成部分

2.2.1 种群与个体

在遗传算法中,一个种群是由一组个体组成的集合,每个个体代表了一个潜在的解。在解决旅行商问题(TSP)时,一个个体可以表示为一条特定的路径,即一系列城市的访问顺序。

个体通常由一串编码表示,这些编码可以是二进制串、实数串或者在TSP中常见的城市排列串。每个个体都拥有一个与问题相关的适应度值,表示了该个体作为问题解的质量。在TSP中,这个适应度值通常是路径的倒数,即路径长度的倒数,因为我们想要最小化路径长度。

种群的大小会影响算法的搜索能力和收敛速度。一个较大的种群有助于保持多样性,可能包含更多高质量的基因,从而提升算法找到最优解的概率。然而,种群越大,算法的计算开销也会越大。

2.2.2 遗传操作:选择、交叉和变异

选择(Selection)、交叉(Crossover)和变异(Mutation)是遗传算法中三个主要的操作,它们共同作用于种群,推动算法的搜索过程。

选择 操作的目的是从当前种群中挑选出表现较好的个体,遗传到下一代。这通过适应度函数来实现,通常采用轮盘赌选择、锦标赛选择等策略,保证了适应度高的个体有更高的机会被选中。

交叉 操作模仿自然界生物的遗传机制,通过交换父母个体的部分基因生成新的个体。在TSP问题中,交叉操作要特别设计以保持路径的有效性,例如顺序交叉(OX)、部分映射交叉(PMX)等。通过交叉,算法能够探索解空间中的新区域,促进优良基因的组合。

变异 操作则是在个体的基因上引入随机变化,以防止算法过早收敛到局部最优解。在TSP中,变异可以是交换两个城市的位置,或者逆转城市序列的一部分。变异操作保证了种群的多样性,是算法跳出局部最优的关键。

2.2.3 适应度函数的作用与设计

适应度函数是衡量个体适应环境能力的函数,对于遗传算法来说至关重要。在TSP中,适应度函数通常是路径长度的倒数,因为我们希望找到一条尽可能短的路径。

一个好的适应度函数设计不仅能够准确反映个体的优劣,还能够保证算法的高效搜索。设计适应度函数时,需要考虑以下几个方面:

  • 函数形态 :适应度函数应当能够区分不同的个体。在TSP中,这意味着不同的路径长度应当得到不同的适应度值。
  • 计算复杂度 :适应度函数应尽可能简洁,以便快速评估大量个体。
  • 公平性 :适应度函数对所有个体应持相同标准,避免对某些个体有偏见。
  • 可调整性 :在某些情况下,可能需要动态调整适应度函数,以适应不同的搜索阶段。

设计一个好的适应度函数是遗传算法应用中的关键挑战之一。通过对适应度函数的精心设计,可以显著提高遗传算法在特定问题上的性能,尤其是在解决复杂、多变的优化问题时更为重要。

3. 初始化种群步骤

种群初始化是遗传算法中至关重要的第一步,它决定了算法搜索过程的起点和种群的多样性。良好的初始化策略能够帮助遗传算法更快地收敛至问题的最优解或者满意解。

3.1 种群初始化方法

3.1.1 随机初始化策略

随机初始化是遗传算法中最常用的方法之一,它简单、高效。在随机初始化过程中,每个个体的基因都是随机生成的,确保了种群具有较高的多样性。随机初始化方法适用于那些对初始解没有特定要求的优化问题。

import numpy as np

def random_population(num_individuals, chromosome_length):
    return np.random.randint(0, 2, (num_individuals, chromosome_length))

# 生成5个个体,每个个体长度为10的随机种群
population = random_population(5, 10)

在上述代码中,我们使用了 numpy 库的 randint 方法生成了一个由0和1组成的数组,每个个体表示为一个长度为10的二进制序列,这样就创建了一个随机种群。

3.1.2 基于特定规则的初始化

除了随机初始化外,基于问题特性或先验知识的初始化方法能够提供更接近最优解的初始种群。这种方法通常可以缩短算法找到最优解的时间。例如,在解决旅行商问题(TSP)时,可以采用贪心算法生成一个较短的循环路径作为初始种群。

def greedy_tsp_solution(distances):
    num_cities = len(distances)
    unvisited = set(range(num_cities))
    start = unvisited.pop()
    path = [start]

    while unvisited:
        current = path[-1]
        next_city = min(unvisited, key=lambda city: distances[current][city])
        path.append(next_city)
        unvisited.remove(next_city)

    return path

# 假设distances为一个表示城市间距离的对称矩阵
initial_path = greedy_tsp_solution(distances)

在这个例子中,我们使用贪心策略从一个城市出发,每次选择距离当前城市最近的未访问城市,直到所有城市都被访问过,从而得到一个初始解。

3.2 种群初始化的重要性与影响

3.2.1 种群多样性与收敛速度

种群的多样性是指种群中个体的基因差异程度,多样性高意味着种群有更广的探索范围。如果种群初始化时多样性不足,可能导致算法过早收敛到局部最优解,失去全局搜索能力。

3.2.2 问题规模与初始化策略的匹配

问题的规模决定了种群初始化的复杂度。对于小规模问题,随机初始化可能就足够了。但对于大规模问题,我们可能需要更加精心设计的初始化策略来保证算法性能。

在初始化种群时,需要根据问题的具体情况和求解需求选择合适的策略,既不能让种群过于分散而耗费过多的搜索资源,也不能让种群过于集中而陷入局部最优。因此,初始化种群是一个需要结合问题特性和算法性能进行细致考量的过程。

4. 适应度函数设计

4.1 适应度函数的作用与要求

4.1.1 如何衡量个体的优劣

适应度函数是遗传算法中用于评价解的优劣,并以此为基础选择优秀个体遗传到下一代的关键工具。在旅行商问题(TSP)中,一个好的适应度函数必须能够准确反映一条路径的优劣,即路径的总距离越短,对应的适应度值应当越高。衡量个体的优劣通常需要考虑以下因素:

  • 路径总长度 :一个个体的路径越短,其适应度值应该越高。
  • 解的质量 :不仅仅是路径长度,解的稳定性、可行性等也是衡量优劣的标准。
  • 多样性维护 :适应度函数应避免早熟收敛,保持种群的多样性。

4.1.2 适应度函数的评价标准

一个好的适应度函数应具备以下特点:

  • 公正性 :能够公平地评价每个个体,避免对某类个体产生偏好。
  • 敏感性 :对个体质量的微小变化反应敏感,以便于进行有效的选择。
  • 稳定性和一致性 :在迭代过程中保持评价标准的一致性,避免出现大的波动。

4.2 设计适应度函数的策略

4.2.1 基于问题特性的适应度函数

针对TSP的适应度函数设计需要考虑路径的总长度,同时也要考虑到求解过程的效率和解的稳定性。设计时可采用以下策略:

  • 倒数法 :路径越短,其适应度值设定为路径长度的倒数,即 f(x) = 1 / total_distance(x)
  • 指数法 :使用路径长度的指数函数,路径越短,适应度指数越高,即 f(x) = exp(1 / total_distance(x))
  • 惩罚函数法 :对于违反约束条件的路径,通过增加惩罚项来降低其适应度值。

4.2.2 适应度函数与遗传算法性能的关系

适应度函数的设计直接影响到遗传算法的性能。例如,如果适应度函数设计得过于平坦,即优秀个体和较差个体之间的适应度值差距不大,那么优秀个体就无法明显脱颖而出,导致选择过程缺乏方向性。反之,如果适应度函数过于陡峭,可能会导致早熟收敛,即算法过早地陷入局部最优解。

此外,适应度函数还需要与选择压力相结合,即选择机制对个体的适应度差异的反应强度。选择压力太高,可能会导致多样性不足;选择压力太低,则可能减慢算法的收敛速度。

示例代码块展示适应度函数的实现

import numpy as np

def fitness_function(distance_matrix):
    """
    Calculate the fitness of a given path.
    :param distance_matrix: The matrix of distances between cities.
    :return: The fitness value.
    """
    total_distance = sum(distance_matrix[path[-1], path[0]] for path in paths)
    # Using reciprocal for fitness, shorter path has higher fitness.
    return 1 / total_distance

# Example usage:
distance_matrix = np.array([[0, 2, 9, 10], [1, 0, 6, 4], [15, 7, 0, 8], [6, 3, 12, 0]])
paths = [[0, 1, 2, 3], [0, 3, 2, 1]]  # Sample paths
fitness_values = [fitness_function(distance_matrix, path) for path in paths]
print(fitness_values)

上述代码段展示了如何通过一个简单的倒数法来计算TSP中每条路径的适应度值。需要注意的是,适应度函数的设计需要根据实际问题的具体要求进行调整,并可能需要结合其他策略来优化算法的表现。

5. 选择操作方法

5.1 选择操作的目的与方法

5.1.1 选择操作的基本原理

选择操作是遗传算法中的一个基本环节,其核心思想是模拟自然界的“适者生存”法则。在遗传算法中,通过选择操作确保更适应环境的个体有更多的机会被选中并用于产生后代。选择操作的目的是根据个体的适应度来挑选能够参与交叉(杂交)的父代个体。

5.1.2 常用的选择方法:轮盘赌、锦标赛等

选择方法众多,其中最著名的有轮盘赌选择(Roulette Wheel Selection)和锦标赛选择(Tournament Selection)。

  • 轮盘赌选择 是一种按比例的选择方法。每个个体被选中的概率与其适应度成正比,形象地理解为“适应度高的个体所占的轮盘面积大,因此被选中的机会多”。具体操作是计算所有个体适应度总和,然后根据个体适应度与总适应度之比来确定被选择的概率。

  • 锦标赛选择 则涉及到随机挑选若干个体,然后从这组个体中选出适应度最高的个体作为父代。锦标赛选择的过程可以重复多次,直到选出足够的父代个体。这种方法的特点是实现简单,同时可以很容易地控制选择压力。

5.2 选择操作的实现与优化

5.2.1 选择策略对算法性能的影响

选择策略对遗传算法的性能有显著的影响。一个良好的选择机制可以提高算法的收敛速度,并且避免早熟收敛,即算法过早地陷入局部最优解而非全局最优解。

在实现选择操作时,还需考虑到避免适应度较高的个体过早占据整个种群,即所谓的“早熟收敛”问题。可以通过增加随机性(例如在轮盘赌中使用“赌轮”的偏转)或是保留一定数量的适应度较低的个体,来维持种群的多样性。

5.2.2 如何避免早熟收敛

避免早熟收敛是选择操作中的一个重要挑战。实现这一点的方法之一是使用“精英保留”策略,即在每一代中直接保留一部分适应度最高的个体不经过交叉和变异操作,确保优秀基因的传承。

另外,也可以采用“随机配对”方法,让个体随机配对而不是完全依赖适应度值进行配对。通过这种机制,能够避免某个个体过度主导种群,保持了种群的多样性。

示例代码:轮盘赌选择方法

import numpy as np

# 适应度函数,以TSP为例,这里使用一个简单的目标函数
def fitness_function(tour):
    # 假设距离矩阵已经给出
    distance_matrix = [...]  # 省略具体实现
    total_distance = sum([distance_matrix[tour[i], tour[(i + 1) % len(tour)]]
                          for i in range(len(tour))])
    return 1 / (1 + total_distance)  # 距离越短,适应度越高

# 初始化种群
population_size = 100
population = [...]  # 初始化种群

# 计算种群的适应度
fitness = np.array([fitness_function(individual) for individual in population])

# 计算总适应度
total_fitness = np.sum(fitness)

# 轮盘赌选择操作
selected_indices = []
for _ in range(population_size):
    # 生成一个[0, total_fitness)之间的随机数
    random_value = np.random.uniform(0, total_fitness)
    cumulative_sum = 0
    for idx, individual_fitness in enumerate(fitness):
        cumulative_sum += individual_fitness
        if random_value <= cumulative_sum:
            selected_indices.append(idx)
            break

# 使用选择出的个体索引来获取实际的个体
selected_individuals = [population[i] for i in selected_indices]

# 下面可以继续交叉和变异操作...

代码逻辑分析与参数说明

  • fitness_function :定义了一个用于计算TSP解的适应度函数。在这里,我们假设了一个距离矩阵,实际实现中需要根据具体问题进行定义。
  • population :表示当前种群,这里用列表表示,每个元素代表一个解(或称为个体)。
  • fitness :是一个数组,存储了种群中每个个体的适应度值。
  • total_fitness :种群适应度的总和,是轮盘赌选择中的一个重要变量。
  • selected_indices :用于存储每次选择操作得到的个体索引。
  • random_value :表示在[0, total_fitness)之间的一个随机数,用于选择操作。
  • cumulative_sum :累加适应度,当累加值超过 random_value 时停止,这时的 idx 即为被选中的个体索引。

通过上述代码段和逻辑分析,我们了解了轮盘赌选择操作的实现步骤,以及如何用代码来完成这一过程。在实际应用中,可能需要针对问题的具体情况对选择方法进行调整以优化算法的性能。

6. 交叉操作实现

6.1 交叉操作的基本概念与作用

6.1.1 交叉操作的目的与重要性

交叉操作是遗传算法中模拟生物进化过程中的性繁殖的环节,其目的是为了在子代中创造出新的遗传组合,以此来探索解空间中的新区域。它是遗传算法中最重要的遗传操作之一,因为它直接影响到算法的全局搜索能力和收敛速度。通过交叉操作,可以将父代个体的优秀特征组合在一起,有时还能产生比任何父代都更优秀的子代,从而提高算法的优化效率。

6.1.2 交叉操作的类型:单点、多点、均匀等

遗传算法中常见的交叉操作类型有单点交叉、多点交叉和均匀交叉等。单点交叉是指在父代个体的某个随机位置将染色体分为两部分,然后交换父代染色体的片段来生成子代。多点交叉则是选择两个或多个交叉点进行交换,而均匀交叉则是随机地从两个父代的每一位中选择一个基因来构造子代。每种交叉方式都有其特点和适用的场景,可以根据问题的特性选择合适的交叉方式。

6.2 交叉操作的设计与实现

6.2.1 交叉概率的确定

交叉概率(pc)是决定交叉操作发生的频率,它是一个介于0和1之间的数值。一般来说,交叉概率设置得较高时,能够增加种群的多样性,有利于探索解空间,但过高的交叉概率可能会破坏优秀的基因组合;相反,较低的交叉概率虽然能够保护优秀基因,但可能导致算法过早收敛。因此,交叉概率的确定需要依据具体的优化问题和实验来调整,以期达到最好的优化效果。

6.2.2 交叉策略的优化与选择

为了优化交叉策略,可以采用自适应交叉概率,即根据算法运行的当前代数或种群的多样性来动态调整交叉概率。例如,在算法的早期阶段采用较高的交叉概率以增强多样性,在算法的后期逐渐降低以稳定优秀的解。另外,还可以引入精英策略,即保留一部分最优个体不参与交叉操作,直接遗传到下一代,以保证解的质量。这些策略的引入可以显著提高遗传算法的搜索效率和解的质量。

代码示例:交叉操作的实现

假设我们使用Python语言实现一个简单的单点交叉操作,下面提供了一个示例代码:

import random

def single_point_crossover(parent1, parent2):
    crossover_point = random.randint(1, len(parent1)-1)
    child1 = parent1[:crossover_point] + parent2[crossover_point:]
    child2 = parent2[:crossover_point] + parent1[crossover_point:]
    return child1, child2

# 假设父代个体为染色体表示
parent1 = [1, 0, 1, 0, 1, 0, 1]
parent2 = [0, 1, 0, 1, 0, 1, 0]

# 执行单点交叉操作
child1, child2 = single_point_crossover(parent1, parent2)
print("Child 1:", child1)
print("Child 2:", child2)

代码逻辑分析

上述代码中定义了一个名为 single_point_crossover 的函数,它接收两个父代个体(这里以列表形式表示染色体),然后随机选择一个交叉点,并在该点将两个父代个体的染色体进行交换,产生两个子代个体。交叉点的选择是随机的,范围在1到染色体长度减1之间,以确保交叉点不位于染色体的两端。

参数说明

在上述代码中, crossover_point 是关键参数,它决定了交叉发生的位置。随机数生成函数 random.randint 的范围是根据输入的父代染色体长度确定的,确保交叉点有效。

通过本章节的介绍,我们可以看到,交叉操作在遗传算法中扮演着至关重要的角色。其设计不仅要考虑交叉策略本身,还需要关注与交叉操作紧密相关的其他因素,如交叉概率的设定和自适应策略的引入。合理的设计和实现交叉操作,可以有效提升遗传算法的性能,使得求解TSP问题的效率得到显著的提高。在下一章节中,我们将详细探讨变异操作的实现及其对算法性能的影响。

7. 变异操作策略

遗传算法中的变异操作是模拟生物进化过程中基因突变的机制,它有助于维持种群的多样性,防止算法过早地收敛到局部最优解,从而增加找到全局最优解的可能性。变异操作的实施为算法提供了跳出局部最优解陷阱的途径,同时也为算法探索解空间带来新的可能。

7.1 变异操作的原理与必要性

7.1.1 变异操作的作用与分类

变异操作在遗传算法中的作用是随机地改变个体的某些基因,以期产生新的特征。这种改变可以是对某个个体的一点小调整,也可以是根本性的改造,它引入新的遗传多样性,帮助算法跳出局部最优解,继续在解空间内进行有效搜索。变异的分类主要可以分为:

  • 位点变异 :改变个体染色体上某个位点的基因值。
  • 插入变异 :将某个个体的部分基因序列移动到其它位置。
  • 逆转变异 :对个体的某个染色体片段进行逆转。
  • 均匀变异 :按照一定的概率,均匀地改变染色体上的每个基因。

7.1.2 变异概率的确定与调整

变异概率是变异操作中一个重要的参数,它决定了算法中变异发生的频率。如果变异概率过高,算法可能会变成随机搜索,破坏了已经得到的优秀解;而如果变异概率过低,算法又会缺乏足够的探索能力,容易陷入局部最优。因此,变异概率的确定和调整对于遗传算法的成功至关重要,通常需要根据具体问题的需要进行多次试验。

7.2 变异操作的实现与改进

7.2.1 变异策略的创新

为了提高遗传算法的性能,研究人员提出了多种变异策略。常见的变异策略改进包括:

  • 自适应变异 :根据算法的迭代情况动态调整变异概率,如在初始阶段设置较高变异概率以保证多样性,在后期降低变异概率以稳定优秀解。
  • 多种群变异 :利用多个种群并行搜索,每个种群采用不同的变异策略。
  • 基于解的适应度的变异 :为适应度不同的个体设置不同的变异概率,适应度低的个体有更大的概率进行变异。

7.2.2 变异对算法全局搜索能力的影响

变异操作对算法的全局搜索能力有着显著的影响。通过变异,算法能够在解空间中引入新的点,从而可能找到更好的解。然而,变异操作也要适度,过多的变异会削弱算法的收敛性,而不足的变异则可能导致算法快速收敛于局部最优解。因此,设计合理的变异策略和控制好变异概率是遗传算法实现成功的关键之一。

在实际应用中,变异策略的选择和调整要根据问题的具体特性和解空间的特性来确定。通过实验和分析,找到最适合问题的变异策略,才能保证遗传算法有效地求解问题。下一章将探讨替换操作流程,这是算法中另一个关键的步骤,它直接关系到算法的收敛性和解的质量。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:旅行商问题(TSP)是NP完全问题,要求旅行商访问多个城市各一次并返回起点,目标是总旅行距离最短。遗传算法是解决此类问题的有效手段,通过模仿自然选择过程迭代优化种群,实现对TSP的高效求解。算法包括初始化种群、适应度评估、选择、交叉、变异和替换等关键步骤。本文档包含遗传算法的实现代码和详细注释,辅助读者深入理解并应用遗传算法求解TSP问题。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值