CODEVS_2800 送外卖 状态压缩+动态规划

本文深入探讨了一种解决外卖配送问题的算法,通过状态压缩动态规划和Floyd算法求解最短路径,旨在实现最小化配送总时间的目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:http://codevs.cn/problem/2800/

题目描述 Description

有一个送外卖的,他手上有n份订单,他要把n份东西,分别送达n个不同的客户的手上。n个不同的客户分别在1~n个编号的城市中。送外卖的从0号城市出发,然后n个城市都要走一次(一个城市可以走多次),最后还要回到0点(他的单位),请问最短时间是多少。现在已知任意两个城市的直接通路的时间。

输入描述 Input Description

第一行一个正整数n (1<=n<=15)

接下来是一个(n+1)*(n+1)的矩阵,矩阵中的数均为不超过10000的正整数。矩阵的i行j列表示第i-1号城市和j-1号城市之间直接通路的时间。当然城市a到城市b的直接通路时间和城市b到城市a的直接通路时间不一定相同,也就是说道路都是单向的。

输出描述 Output Description

一个正整数表示最少花费的时间

样例输入 Sample Input
3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
样例输出 Sample Output

8

数据范围及提示 Data Size & Hint

1<=n<=15

这道题很容易想到状压dp,首先跑一遍floyd求出各个点之间的最短路,然后dp。

状态是dp[i][j]表示状态为i(二进制,表示是否访问过每个点),在位置j时的最短路。

转移就是:dp[i][j]=min(dp[i-(1<<v)][u]+grid[u][v],dp[i][j]),其中v是当前位置,u是上一个状态的位置。

需要注意的是dp的顺序应该是由含1的个数少的二进制到1的个数高的二进制;由于最开始就在0位置,所以dp[(1<<n)-1][0]不可能被转移到,所以最后的答案应该是ans=min(ans,dp[(1<<n)-1][i]+grid[i][0]),其中0<=i<n。

详见代码:

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<climits>
#define INF INT_MAX
#define MAX_S 1<<16
#define MAX_N 17
using namespace std;

struct node
{
    int val,num;
    node(int v,int n)
        {val=v;num=n;}
    node(){}
};

node one[MAX_S];
int grid[MAX_N][MAX_N];
int n;
int dp[MAX_S][MAX_N];
int numOfOne(int x)
{
    int res=0;
    for(int i=0;i<n;i++)
        if((x>>i)&1)res++;
    return res;
}

void floyd()
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++)
                grid[i][j]=min(grid[i][j],grid[i][k]+grid[k][j]);
}

bool cmp(node a,node b)
{
    return a.num<b.num;
}

int main()
{
    scanf("%d",&n);
    n++;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            scanf("%d",&grid[i][j]);
    int totS=1<<n;
    for(int i=0;i<totS;i++)one[i]=node(i,numOfOne(i));

    for(int i=0;i<totS;i++)
        for(int j=0;j<n;j++)
            dp[i][j]=INF;

    floyd();
    sort(one,one+totS,cmp);
    dp[1][0]=0;
    for(int i=0;i<totS;i++)
    {
        int s=one[i].val;
        for(int v=0;v<n;v++)
        {
            if(!((s>>v)&1))continue;
            int t=s-(1<<v);
            int tmp=INF;
            for(int u=0;u<n;u++)
            {
                if((!((t>>u)&1))||dp[t][u]==INF)continue;
                tmp=min(tmp,dp[t][u]+grid[u][v]);
            }
            if(tmp!=INF)
                dp[s][v]=tmp;
        }
    }
    int ans=INF;
    for(int i=0;i<n;i++)
        ans=dp[totS-1][i]==INF?ans:min(ans,dp[totS-1][i]+grid[i][0]);
    cout<<ans<<endl;
    return 0;
}


### 校园外卖路径优化中的动态规划算法 校园外卖系统的配路径优化是一个复杂的问题,通常涉及多目标优化,例如最短距离、最低成本或最快达时间。为了实现这一目标,可以采用多种算法,其中遗传算法和动态规划是两种常见的解决方案。 #### 遗传算法的应用 遗传算法是一种模拟自然选择过程的全局优化方法,在解决复杂的组合优化问题方面表现优异。对于带有时间窗约束的外卖车辆路径规划问题,可以通过遗传算法找到近似最优解[^5]。具体而言,遗传算法通过编码个体表示可能的路径集合,并利用交叉、变异等操作不断进化种群,最终收敛至较优解。 以下是基于Python的一个简单遗传算法框架用于路径优化: ```python import random from deap import base, creator, tools # 定义适应度函数 (假设已知各节点之间的距离矩阵 distance_matrix) def eval_fitness(individual, distance_matrix): total_distance = 0 for i in range(len(individual)-1): from_node = individual[i] to_node = individual[i+1] total_distance += distance_matrix[from_node][to_node] return total_distance, # 初始化DEAP环境 creator.create("FitnessMin", base.Fitness, weights=(-1.0,)) creator.create("Individual", list, fitness=creator.FitnessMin) toolbox = base.Toolbox() toolbox.register("indices", random.sample, range(len(distance_matrix)), len(distance_matrix)) toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.indices) toolbox.register("population", tools.initRepeat, list, toolbox.individual) toolbox.register("evaluate", eval_fitness, distance_matrix=distance_matrix) toolbox.register("mate", tools.cxOrdered) toolbox.register("mutate", tools.mutShuffleIndexes, indpb=0.05) toolbox.register("select", tools.selTournament, tournsize=3) # 运行遗传算法 pop = toolbox.population(n=50) hof = tools.HallOfFame(1) stats = tools.Statistics(lambda ind: ind.fitness.values) stats.register("avg", numpy.mean) stats.register("min", numpy.min) result_pop, logbook = algorithms.eaSimple(pop, toolbox, cxpb=0.7, mutpb=0.2, ngen=40, stats=stats, halloffame=hof, verbose=True) ``` 上述代码展示了如何使用遗传算法求解路径优化问题。需要注意的是,实际应用中需定义具体的`distance_matrix`并调整参数以适配特定场景。 #### 动态规划的方法 动态规划适用于状态空间较小的情况,其核心思想是将大问题分解为若干子问题并通过存储中间结果减少重复计算。针对外卖路径优化,可将其建模为旅行商问题(TSP),即寻找访问所有客户点一次且仅一次的最短回路。 下面给出一个简单的动态规划伪代码描述: ```plaintext function TSP_DynamicProgramming(distances): n = number of nodes dp = array[n][2^n], initialized with infinity # Base case: start at node 0 and visit no other nodes yet. dp[0][1 << 0] = 0 for mask in all subsets excluding the empty set: for u in unvisited nodes within mask: prev_mask = mask without u for v in visited nodes within prev_mask: if dp[v][prev_mask] + distances[v][u] < dp[u][mask]: dp[u][mask] = dp[v][prev_mask] + distances[v][u] min_cost = infinity final_mask = full subset including all nodes for last in all nodes except starting point: if dp[last][final_mask] + distances[last][start] < min_cost: min_cost = dp[last][final_mask] + distances[last][start] return min_cost ``` 此方法的时间复杂度较高(O(2^n * n²)),因此适合于规模有限的小型网络。 #### 结合技术架构的设计思路 在实际开发过程中,应考虑整个系统的模块化设计。根据已有文献提到的内容[^2],完整的校园外卖系统至少需要以下几个部分协同工作:用户管理、餐品管理、订单管理、配管理和数据分析。而路径优化作为配环节的核心功能之一,应当被独立封装并与地图服务API对接,以便实时获取地理坐标信息并更新最佳路线建议。 另外值得注意的是,无论是选用哪种算法进行路径优化,都应在项目初期充分评估其实现难度与预期效果,确保整体设计方案具备可行性的同时也留有足够的扩展空间[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值