我正在做一个项目,当他们到达消防局接受卡车时,将志愿消防员放在座位上。
还有一些消防员拥有一些没有驾驶执照的驾驶执照,有些则有团队领导教育。
所以我的想法是通过GPS跟踪它们并将服务器发送到消防局的整数距离以及每种教育类型。
然后每5秒运行算法并根据新的GPS坐标改变他们的座位,直到1靠近车站,然后标记为座位。
这应该发生,直到没有空座位或者不再有消防员打电话或所有被叫消防队员到达
我想要帮助的棘手的事情(除非我的想法是最佳的),是让消防员最理想的位置。
我正在考虑列出可能的角色的优先级列表。 以及必须离开车站的车辆优先列表。
然后选择最高优先级的车辆和最高优先级的角色,并用最近的接受过教育的消防员填写。
但是,如果他是一名车手,但已经进入了领队位置,而且只有一名车手即将到来,并且有更多的队员前来,两辆车不得不离开,这将是一个错误的解决方案,因为第二辆车不能离开。再次,如果驱动程序而非团队领导者是最高优先级,那么如果最接近的是设置为驱动程序,但也是唯一一个带有团队领导者教育的人,但更多的驱动程序即将到来,那么它也将是错误的。
算法的任何想法都有效吗?或者有人知道这个算法吗?
答案 0 :(得分:0)
你是对的,这种贪婪的方法不一定会给你一个最佳的解决方案。您是否已查看/听说过线性编程或更具体的整数编程:http://en.wikipedia.org/wiki/Integer_programming
简而言之,整数编程是解决这些类型的调度问题的一种技术。问题有一些目标,你希望最大化或最小化,并受到各种(线性)约束。整数,因为我们不能有半个志愿者。
根据您的描述,目标函数可以是最小化未部署的卡车数量和总等待时间。对于不同的卡车,您可能会有不同的成本来捕捉不同的车辆优先级。
约束将包括每辆车至少需要一名驾驶员,至少一名车队领队,并且志愿者只能分配给一辆车。可能还有其他一些你没有描述的限制,例如没有人可以在基地等待超过20分钟。
如果您搜索整数编程和调度,您应该找到一些代码示例。您可能需要求解器才能提供帮助。 Wiki有一个相当全面的列表,选择将取决于您的编程语言首选项和预算:http://en.wikipedia.org/wiki/Linear_programming#Solvers_and_scripting_.28programming.29_languages
答案 1 :(得分:0)
这样的事情怎么样.. 正如你所注意到的唯一相互矛盾的情况是当你有一名可以成为司机和领导者的消防员时......因为它只能占据一个位置......但可能会阻挡另一个......
所以不要从他们开始..首先从那些拥有以太网潜水员许可证或领导者教育的人开始......因为那些已经拥有预定位置(他们唯一能够承担的)......
填写之后..分配那些可以进行以太工作的人,为缺少的座位分配,或者如果他们离近的话就更换一些。
在拥有一系列司机和一系列领导人之后......将他们按照距消防站的距离进行排序并成对分配给卡车..然后填充卡车的其余部分......按照ETA的顺序从队列中删除..不确定它是否会始终提供最佳解决方案..但似乎非常优化..对于您希望一些代码? C#?
这个问题让我很好奇。这是我正在谈论的代码..如果你不使用它的前夕using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace FF
{
class Program
{
[Flags]
public enum Skill
{
None = 0,
Driver = 1,
TeamLeader = 2,
}
public class FireFighter : IComparable<FireFighter>
{
public int ID;
public Skill Skills;//the skills that he has
public Skill Assigned;//the one that he will be deployed with
public int ETA;
public override string ToString()
{
return ID + "(" + Skills + ")" + " @ " + ETA + " minutes as " + this.Assigned;
}
int IComparable<FireFighter>.CompareTo(FireFighter other)
{
return this.ETA.CompareTo(other.ETA);
}
}
public class Truck
{
public int ID;
public int Capacity;
public List<FireFighter> Crew = new List<FireFighter>();
}
static int TotalStationTrucks = 8;
static List<Truck> Trucks = new List<Truck>();
static List<FireFighter> Team = new List<FireFighter>();
static Random Rnd = new Random();
static void Main(string[] args)
{
//create the sample data
int nAvailableSeats = 0;
for (int i = 0; i < TotalStationTrucks; i++)
{
Truck oTruck = new Truck();
oTruck.ID = i;
nAvailableSeats += oTruck.Capacity = Rnd.Next(4, 7);//seats between 4 - 6
Trucks.Add(oTruck);
}
for (int i = 0; i < nAvailableSeats * 2; i++)//add twice the amount of FF we need for all trucks
{
FireFighter oFireFighter = new FireFighter();
oFireFighter.ID = i;
oFireFighter.ETA = Rnd.Next(Int16.MaxValue);
Team.Add(oFireFighter);
}
for (int i = 0; i < Trucks.Count * 2; i++)//add twice the drivers we need
{
FireFighter oFireFighter = Team[Rnd.Next(Team.Count)];
oFireFighter.Skills |= Skill.Driver;
}
for (int i = 0; i < Trucks.Count * 2; i++)//add twice the leaders we need
{
FireFighter oFireFighter = Team[Rnd.Next(Team.Count)];
oFireFighter.Skills |= Skill.TeamLeader;
}
for (int i = 0; i < Trucks.Count * 2; i++)//add twice the multitaskers we need
{
FireFighter oFireFighter = Team[Rnd.Next(Team.Count)];
oFireFighter.Skills = (Skill.TeamLeader|Skill.Driver);
}
//Truck that are going to be deployed
int nTrucksToDeploy = Rnd.Next(2, Trucks.Count);
// distribute firefighter by ETA to minimize truck deploy
//*******************************************************
//Sort by ETA
Team.Sort();
//get top the ones that can only drive
List<FireFighter> oSelectedDrivers = Team.FindAll(delegate(FireFighter item) { return item.Skills == Skill.Driver; }).GetRange(0, nTrucksToDeploy);
oSelectedDrivers.ForEach(delegate(FireFighter item) { item.Assigned = Skill.Driver; });
//get top the ones that can only lead
List<FireFighter> oSelectedLeaders = Team.FindAll(delegate(FireFighter item) { return item.Skills == Skill.TeamLeader; }).GetRange(0, nTrucksToDeploy);
oSelectedLeaders.ForEach(delegate(FireFighter item) { item.Assigned = Skill.TeamLeader; });
//put them on a list of already assigned
List<FireFighter> oAssigned = new List<FireFighter>();
oAssigned.AddRange(oSelectedDrivers);
oAssigned.AddRange(oSelectedLeaders);
//get the ones that can do ether job
List<FireFighter> oMultitaskers = Team.FindAll(delegate(FireFighter item) { return item.Skills == (Skill.Driver | Skill.TeamLeader); });
//sort by ETA
oMultitaskers.Sort();
oAssigned.Sort();
//put a multitaskers in the queue if he is gonna arrive earlier than the most delayed
while (oMultitaskers[0].ETA < oAssigned[oAssigned.Count - 1].ETA)
{
FireFighter oIsOut = oAssigned[oAssigned.Count - 1];
FireFighter oIsIn = oMultitaskers[0];
//swap tasks
oIsIn.Assigned = oIsOut.Assigned;
oIsOut.Assigned = Skill.None;
//remove from respective queues
oAssigned.RemoveAt(oAssigned.Count - 1);
oMultitaskers.RemoveAt(0);
//Add the multitasker to queue
//and if you are questioning if the could get a better solution by choosing another assignment
//that as no influence.. the optmizing condition is removing the slowest that was on queue
oAssigned.Add(oIsIn);
//the out guy is not added for two reasons
//1st is not a multitasker
//2nd and most importante.. he was the one with the highest ETA, we will NEVER gain by replacing another driver with this one
//oMultitaskers.Add(oIsOut);
oMultitaskers.Sort();
oAssigned.Sort();
}
//start filling the trucks take one of each from top, wich means the first truck will have the earliest departure
for (int i = 0; i < nTrucksToDeploy; i++)
{
int nDriverIndex = oAssigned.FindIndex(delegate(FireFighter item) { return item.Assigned == Skill.Driver; });
Trucks[i].Crew.Add(oAssigned[nDriverIndex]);
oAssigned.RemoveAt(nDriverIndex);
int nLeaderIndex = oAssigned.FindIndex(delegate(FireFighter item) { return item.Assigned == Skill.TeamLeader; });
Trucks[i].Crew.Add(oAssigned[nLeaderIndex]);
oAssigned.RemoveAt(nLeaderIndex);
}
//now fill the rest of the crew.. also ordered by ETA
List<FireFighter> oUnassigned = Team.FindAll(delegate(FireFighter item) { return item.Assigned == Skill.None; });
oUnassigned.Sort();
for (int i = 0; i < nTrucksToDeploy; i++)
{
while (Trucks[i].Crew.Count < Trucks[i].Capacity)
{
Trucks[i].Crew.Add(oUnassigned[0]);
oUnassigned.RemoveAt(0);
}
}
//dump truck data
Trace.WriteLine(String.Format("{0} trucks to be deployed",nTrucksToDeploy));
for (int i = 0; i < nTrucksToDeploy; i++)
{
Trace.WriteLine(new String('-', 20));
Truck oTruck = Trucks[i];
oTruck.Crew.Sort();
Trace.WriteLine(String.Format("truck {0} estimated time of departure: {1}",oTruck.ID,oTruck.Crew[oTruck.Crew.Count-1].ETA));
for (int j = 0; j < oTruck.Crew.Count; j++)
{
FireFighter oFireFighter = oTruck.Crew[j];
Trace.WriteLine(String.Format("{0}({1})\t @ {2} minutes as \t{3}", oFireFighter.ID, oFireFighter.Skills, oFireFighter.ETA, oFireFighter.Assigned));
}
}
Trace.WriteLine(new String('#', 20));
//list the team
for (int i = 0; i < Team.Count; i++)
{
FireFighter oFireFighter = Team[i];
Trace.WriteLine(String.Format("{0}({1})\t @ {2} minutes as \t{3}", oFireFighter.ID, oFireFighter.Skills, oFireFighter.ETA, oFireFighter.Assigned));
}
}
}
}