部分和(partial sum)在算法求解中的作用

  • C++ 的 STL 库的 <numeric> 头文件的 partial_sum 函数已实现了对某一序列的 partial sum。
    • partial_sum(first, last, dest);

1. 部分和的引入

并非什么高级深奥的技巧,但却十分有用。

假设按照降序排列 N 个学生的考试成绩并保存到数组 scores[],现在想要编写求出从第 a 名到第 b 名成绩的函数 average(a, b),最简单的方法是,将 scores[a] 到 scores[b] 的乘积全部相加,然后除以 b-a+1。

这种方法的循环次数最大会达到 O(N)如果只计算 1 次平均值,这种时复杂度就足够了。但多次调用 average() 的话,就需要对函数进行优化。

此时需要用到部分和(partial sum)(或者累加和)的概念。部分和就是,对从数组起始位置到当前任一位置求和并保存的数组(类似于概率理论中的分布函数的概念)。

pSum[j]=i=0jscores[i]

预先计算 psum 就能在 O(1) 时间内求出 scores[] 在特定区间的和(君子)。假设 psum[-1] = 0,那么,scores[a] 和 scores[b] 之间的和可按照如下方式计算:

psum[b]psum[ba+1]

部分和的简单计算:

int A[101], pSum[101], pSqSum[101];
sort(A, A+n);
pSum[0] = A[0]; 
pSqSum[0] = A[0]*A[0];
for (int i = 1; i < n; ++i){
    pSum = pSum[i-1] + A[i];
    pSqSum = pSqSum[i-1] + A[i]*A[i];
}

一定千万要注意,在求解某一区域的部分和的时候,比如 [a, b]pSum[a] 本身是包含数组在 a 处的值的,

// ∑_a^b A[i] ⇒ 
pSum[b] - (a == 0 ? 0 : pSum[a - 1]);

2. 均值、方差

v==1ba+1i=ab(A[i]μ)2i=abA[i]2ba+1μ2

3. 从一维到二维数组

记, psum[y,x]=i=0yj=0xA[i,j] ,则从 (y1,x1) (y2,x2) 之间矩形所包含元素的和,

sum([y1,x1],[y2,x2])=psum(y2,x2)psum(y21,x1)psum(y1,x21)+psum(y11,x11)

int gridSum(const vector<vector<int>>& psum, int y1, int x1, int y2, int x2) {
    int ret = psum[y2][x2];
    if (y1 > 0) ret -= psum[y1-1][x2];
    if (x1 > 0) ret -= psum[y2][x1-1];
    if (x1 > 0 && y1 > 0) ret += psum[y1-1][x1-1];
    return ret;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是一个使用遗传算法解决配送心选址问题的Python代码: ```python import numpy as np from scipy.spatial.distance import cdist from scipy.optimize import minimize from functools import partial import random def fitness_function(x, demand_points, distribution_centers): distances = cdist(demand_points, distribution_centers[x, :]) return -np.sum(np.min(distances, axis=1)) def genetic_algorithm(number_of_variables, fitness_function, population_size=50, number_of_generations=100, crossover_fraction=0.8, mutation_fraction=0.02): # 初始化种群 population = np.random.randint(2, size=(population_size, number_of_variables)) for i in range(number_of_generations): fitness_values = np.array([fitness_function(x, demand_points, distribution_centers) for x in population]) # 选择 sorted_indices = np.argsort(fitness_values)[::-1] population = population[sorted_indices] # 交叉 crossover_point = int(crossover_fraction * number_of_variables) for j in range(population_size // 2): parent1, parent2 = population[2*j], population[2*j+1] child1 = np.concatenate((parent1[:crossover_point], parent2[crossover_point:])) child2 = np.concatenate((parent2[:crossover_point], parent1[crossover_point:])) population[2*j], population[2*j+1] = child1, child2 # 变异 for j in range(population_size): for k in range(number_of_variables): if random.random() < mutation_fraction: population[j, k] = 1 - population[j, k] # 最优解 best_individual = population[0] best_fitness = fitness_values[0] print('Generation {0}: Best Fitness = {1}'.format(i+1, best_fitness)) return best_individual, best_fitness # 需求点和配送心的坐标 demand_points = np.random.rand(60, 2) distribution_centers = np.random.rand(15, 2) # 遗传算法参数 number_of_variables = 15 population_size = 50 number_of_generations = 100 crossover_fraction = 0.8 mutation_fraction = 0.02 # 运行遗传算法 fitness_function_partial = partial(fitness_function, demand_points=demand_points, distribution_centers=distribution_centers) best_individual, best_fitness = genetic_algorithm(number_of_variables, fitness_function_partial, population_size, number_of_generations, crossover_fraction, mutation_fraction) # 输出结果 selected_centers = np.where(best_individual == 1)[0] print('选择的配送心坐标是:') print(distribution_centers[selected_centers, :]) print('总距离为:', -best_fitness) ``` 这段代码使用遗传算法寻找最佳配送心的选择方案,其适应度函数的计算方式为:计算所有需求点到选的配送心的距离,并将最小距离求和作为适应度值。选的配送心的数量为6个。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五道口纳什

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值