北邮2019计导下 [project] 外卖订单模拟 4.算法部分

说来惭愧,我并没有什么好的算法,这个算法还是我和室友在宿舍里随便yy出来的,可能并不优秀,但是帮我们完成了整个大作业。
每次去讨论算法的课,看别人什么bfs、dfs、遗传算法各种方法玩的溜的很。窝,窝听不懂啊。
中间去蹭了一节三大班的计导课,收获比较大,从一个大佬组的ppt中,我得知了这是
开始引用
在极强约束下(时间窗口和店家住处经过排序)的NP-Hard问题,因而解空间大大小于普通的NP-Hard问题,可以尝试采用基于搜索的启发式(heuristic)算法
本算法(他们的)高度借鉴了M.G Kantor等人在The Orienteering Problem with Time Windows一文中的insertion heunstic算法,并在本题中的模拟地图环境中进行了适配
……

结束引用

看他列出的算法,惊了,跟我yy的算法有异曲同工之妙,都是先生成假想路径然后再评估打分,最后根据评估值选择最优的插入位置。 没必要骗人,当初我去听这个课的时候第一版基本完稿了。
不过也是从他的问题中,我得知了这类问题叫带时间窗的路径优化问题,如果你去知网上搜可以找到不少相关的算法,常见的有蚁群算法。
可是,以我离散的水平,看不懂啊。

安排订单的算法

我的算法安排订单的步骤如下
Created on ProcessOn
在这里插入图片描述

将节点插入骑手路径链表的算法

在这里插入图片描述

骑手信息更新的算法

其中updateSingleRider()函数已知存在问题
在这里插入图片描述

strategy.c

#include "define.h"
#include <stdlib.h>
#include <stdio.h>

const int INF=9999999;
const int velocity=1;
const int Default_Born_Point_Y=8;
const int Default_Born_Point_X=9;
const int Penalty_Factor_Newbie=10;
const int Penalty_Factor_Overdue=10;
int Time_Limit_Per_Order=30;
const int Profit_Per_Order=10;
const int Penalty_Per_Order=50;

extern int CurrentTime;
extern Order* OrderListHead;
extern int OrderCnt;
extern int RiderCnt;
extern Rider* RiderListHead;
extern int Balance;
extern Rider* LastRider;
extern int OrderOverdue;
extern int OrderCompleted;
extern int OrderTaken;
extern Queue OverdueQueue;
extern Queue CompletedQueue;

int matDis(Anchor *a,Anchor *b);
//计算两点的曼哈顿距离
Anchor* duplicateAnchor(Anchor *ori);
//复制一个锚点到一个新锚点
Anchor* duplicateAnchorList(Anchor *ori);
//复制一个链表到新链表
Anchor* appendOrderAssumption(Rider *rider,Anchor *src_ori,Anchor *dst_ori);
//根据骑手当前的位置,将src和dst插入后传回假设的路径
int findMinIndex(int arr[],int n);
//找出数组的最小值
Rider *hireNewbie();
//创建新人骑手节点
void assginSingleOrder(Order *o);
//分配单个订单
void freeAnchorList(Anchor *LinkedListHead);
//释放带头结点的链表,头结点也释放
void updateSingleRider(Rider *rider);
//更新单个骑手的状态
void settleOrder(Order *o);
//结算单笔订单
int isEnd();
//判断派单过程是否结束
void moveRider(Rider *rider);
//根据pos和路径,移动骑手到下一个位置(更新pos)
void updateAllRiders();
//更新所有骑手
void assignOrderPeriodic(int CurrentTime);
//分配某时间刻的所有订单
int estimate(Anchor *path,Rider *rider);
//评估生成路径的优劣
void OrderOverdueFunc(Order *o);
//订单结算时超时的处理
void OrderSuccessFunc(Order *o);
//订单结算时送达的处理

Order* OrderClipStrategy=NULL;

int matDis(Anchor *a,Anchor *b)
{
   
	if(!a||!b) return 0;
	return abs(a->x-b->x)+abs(a->y-b->y);//否则计算曼哈顿距离
}

Anchor *duplicateAnchor(Anchor *ori)
{
   
	if(!ori) return NULL;
	Anchor *currentPtr=(Anchor*)malloc(sizeof(Anchor));
	currentPtr->x=ori->x;
	currentPtr->y=ori->y;
	currentPtr->from=ori->from;
	currentPtr->nextPtr=ori->nextPtr;
	return currentPtr;
}

Anchor* duplicateAnchorList(Anchor *ori)
{
   
	Anchor *r=(Anchor*)malloc(sizeof(Anchor));//新链表的头哨兵
	Anchor *iterator=ori->nextPtr;//原链表的迭代器
	Anchor *currentPtr=NULL,*lastPtr=NULL;
	while(iterator)//迭代原链表
	{
   
		currentPtr=duplicateAnchor(iterator);//复制节点的数据到新节点
		if(!lastPtr)//新链表为空时
		{
   
			r->nextPtr=currentPtr;
			lastPtr=currentPtr;
		}
		else
		{
   
			lastPtr->nextPtr=currentPtr;
			lastPtr=currentPtr;
		}
		iterator=iterator->nextPtr;
	}
	if(!lastPtr) r->nextPtr=NULL;//原链表为空时,新链表也为空
	else lastPtr->nextPtr=NULL;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值