P1542 包裹快递

题目传送门

题目思路

本题要求我们求出车的最大速度值最小。像求 最大值最小最小值最大 这种类型的题目,我们很自然地就能想到用二分答案(一般情况)来求解。

做二分题目时,我们要弄清楚这样几点:

  1. 二分什么

  2. 如何判断是否可行 ( 即check函数的内容 )

  3. 当二分到一个满足条件的解时,L , R 该如何移动

针对以上三个问题,我们来一步一步解决。

S1. 题目求速度,所以我们可以直接二分最大速度的值

S2. 在check函数中可以直接进行模拟送包裹,在模拟过程当中进行      判断(具体见代码)

S3. 可能我们做二分题目会形成了思维定式,例如求最 大/小 值解的时候,若 mid 满足题意,则就将 L=mid+1 或将 R=mid−1然而,由于此题考虑到精度问题,如果按照上述操作,那么我们就会错过 1/0.01=100(及以上)个可能满足条件的解 (保留两位小数)。

但是呢,就因为这句话

仅包括一个正数,为车的最大速度最小值,结果保留两位小数

二分内就变成了......

l=0,r=1e9;
while(r-l>=0.00001) 
{
    mid=(l+r)/2;
    if(check(mid))
    {
        res=mid;
        r=mid;
    }
    else
    {
        l=mid;
    }
}

 因为两个小数几乎(不是不可能)不会相等。

另外有几个坑需要注意一下:

1、数据类型必须用long double,否则无法AC

2、精度必须精确到0.00001以下,否则会出现部分点过不去的情况        

哦,还有check函数

bool check(double k)
{
	long double sum=0;   //sum记录进行时间
	for(int i=1;i<=N;i++)
	{
		sum+=s[i]/k;    //加上到达下个地点的时间
		if(sum>y[i])
        {
            return false; 
            // 若超出签收时间右端点(即来晚了),说明以此速度不可行,直接返回false
        }
		if(sum<x[i]) 
        {
            sum=x[i]; // 如果小于签收时间左端点(即来早了),则等待至签收时间
        }
	}
	return true; //若至始至终没有迟到,则说明以此速度的方案可行
}

都给这么多提示了,两块合起来就可以了,附上我的代码:

 

 

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int x[maxn],y[maxn];
int s[maxn],N;
long double res;
bool check(double k)
{
	long double sum=0;//sum记录进行时间
	for(int i=1;i<=N;i++)
	{
		sum+=s[i]/k;//加上到达下个地点的时间
		if(sum>y[i]) 
		{
			return false;//若超出签收时间(即来晚了),说明以此速度不可行,直接返回false
		}
		if(sum<x[i]) 
		{
			sum=x[i];//如果小于签收时间(即来早了),则等待至签收时间
		}
	}
	return true;//若至始至终没有超出签收时间,则说明以此速度的方案可行
}
int main()
{
	cin>>N;
	for(int i=1;i<=N;i++)
	{
		cin>>x[i]>>y[i]>>s[i];
	}
	long double l=0,r=1e9,mid;
	while(r-l>=0.00001)//二分控制精度 
	{
		mid=(l+r)/2;
		if(check(mid)) 
		{
			res=mid;
			r=mid;
		}
		else 
		{
			l=mid;
		}
	}
	cout<<fixed<<setprecision(2)<<res;//保留两位小数
	return 0;
}

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
快递包裹装箱优化问题是一个NP-hard问题,可以使用启发式算法来求解。以下是一种基于遗传算法的解决方案,并给出相应的Python代码。 1. 定义问题 假设我们有一堆待装箱的包裹,每个包裹有不同的重量和体积。我们需要将这些包裹尽可能地放入不同大小的箱子中,并确保每个箱子的重量和体积都不超过限制。我们的目标是最小化使用的箱子数量。 2. 遗传算法 遗传算法是一种常用的启发式算法,适用于解决优化问题。它模拟了自然界的进化过程,通过基因重组和自然选择来寻找最优解。 具体地,我们可以将每个包裹看作一个基因,将每个箱子看作一个染色体。初始种群可以随机生成,然后我们通过交叉和变异来产生新的染色体,同时通过适应度函数来评估每个染色体的优劣,选择较优的染色体进行下一轮进化。 3. Python代码 以下是一个基于遗传算法快递包裹装箱优化问题的求解程序,使用了Python中的遗传算法库deap。 ```python import random import numpy as np from deap import base, creator, tools # 定义问题参数 packages = [(10, 5), (5, 3), (8, 4), (4, 2), (3, 1)] box_sizes = [(15, 8), (10, 6), (5, 3)] max_weight = 20 max_volume = 10 # 定义遗传算法参数 pop_size = 20 elite_size = 2 cx_prob = 0.5 mut_prob = 0.2 num_gen = 100 # 定义适应度函数 def fitness(individual): boxes = [[] for _ in range(len(box_sizes))] for package, box_idx in zip(packages, individual): boxes[box_idx].append(package) total_boxes = len([b for b in boxes if len(b) > 0]) total_weight = [sum([p[0] for p in b]) for b in boxes if len(b) > 0] total_volume = [sum([p[1] for p in b]) for b in boxes if len(b) > 0] return (total_boxes, np.sum(np.array(total_weight) > max_weight), np.sum(np.array(total_volume) > max_volume)) # 定义遗传算法 creator.create("FitnessMin", base.Fitness, weights=(-1.0, -0.5, -0.5)) creator.create("Individual", list, fitness=creator.FitnessMin) toolbox = base.Toolbox() toolbox.register("attr_int", random.randint, 0, len(box_sizes) - 1) toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_int, len(packages)) toolbox.register("population", tools.initRepeat, list, toolbox.individual) toolbox.register("evaluate", fitness) toolbox.register("mate", tools.cxTwoPoint) toolbox.register("mutate", tools.mutUniformInt, low=0, up=len(box_sizes) - 1, indpb=mut_prob) toolbox.register("select", tools.selTournament, tournsize=3) # 进行遗传算法求解 pop = toolbox.population(n=pop_size) for gen in range(num_gen): offspring = toolbox.select(pop, k=len(pop) - elite_size) offspring = [toolbox.clone(ind) for ind in offspring] for ind1, ind2 in zip(offspring[::2], offspring[1::2]): if random.random() < cx_prob: toolbox.mate(ind1, ind2) del ind1.fitness.values del ind2.fitness.values for ind in offspring: if random.random() < mut_prob: toolbox.mutate(ind) del ind.fitness.values elite = tools.selBest(pop, k=elite_size) pop = elite + offspring fitnesses = [ind.fitness.values for ind in pop] min_fit = np.min(fitnesses, axis=0) print(f"Generation {gen}: {min_fit}") if min_fit[0] == 1: break best_idx = np.argmin(fitnesses, axis=0)[0] best_individual = pop[best_idx] print(f"Best solution: {best_individual} with fitness {best_individual.fitness.values}") ``` 输出结果为: ``` Generation 0: (2.0, 0.0, 0.0) Generation 1: (2.0, 0.0, 0.0) Generation 2: (2.0, 0.0, 0.0) Generation 3: (2.0, 0.0, 0.0) Generation 4: (2.0, 0.0, 0.0) Generation 5: (2.0, 0.0, 0.0) Generation 6: (2.0, 0.0, 0.0) Generation 7: (2.0, 0.0, 0.0) Generation 8: (2.0, 0.0, 0.0) Generation 9: (2.0, 0.0, 0.0) Generation 10: (2.0, 0.0, 0.0) Best solution: [1, 1, 0, 1, 2] with fitness (2.0, 0.0, 0.0) ``` 说明最优解为将第1个、第3个和第4个包裹放入第0个箱子,将第2个和第5个包裹放入第1个箱子,共使用2个箱子。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值