private void NBS(object sender, EventArgs e) { totalDistance = 0; Station[] ss = new Station[stations.Length]; stations.CopyTo(ss, 0); Array.Sort(ss); //找出不需要用送的站點作為補給站之用 List <Station> supplyStation = new List <Station>(); Priority_Queue.SimplePriorityQueue <Station> pq = new Priority_Queue.SimplePriorityQueue <Station>(); for (int i = 0; i < ss.Length; i++) { if (ss[i].Rate != 0) { pq.Enqueue(ss[i], 1); } if (ss[i].Rate == 0) { supplyStation.Add(ss[i]); } } int[] Sequence = new int[totalStation]; for (int i = 0; i < Sequence.Length; i++) { Sequence[i] = -1; } //確定第一站為最需要先被服務的並且直接先決定卡車上的貨物數量 //直接先決定到的時間點剛好為最需要被服務的剛好缺的時點 int[] temp = new int[totalStation]; double time = 0; double cost = 0; Truck truck = null; for (int k = ss.Length - 1; k > -1; k--) { if (ss[k].Rate != 0) { if (ss[k].Rate < 0) //rate < 0 => need to delivery { truck = new Truck(truckcapacity, truckcapacity); temp[0] = truckcapacity / 2; //cost = HoldingShortageSurplus(time, Sequence[0], truck.PickupDelivery(14)); } else if (ss[k].Rate > 0) { truck = new Truck(truckcapacity, 0); temp[0] = -truckcapacity / 2; //cost = HoldingShortageSurplus(time, Sequence[0], truck.PickupDelivery(-14)); } time = startTOvertex[ss[k].StationID] / speed; Sequence[0] = ss[k].StationID; temp[0] = truck.PickupDelivery(temp[0]); cost += HoldingShortageSurplus(time, Sequence[0], temp[0], ref truck); break; } } Station s = null; //開始建構解 int a = 1; bool flag = false; double min = double.MaxValue; double m = 0; int selected = -1; while (time <= timehorizon && a < totalStation) { while (pq.Count != 0) { s = pq.Max(); pq.Remove(s); flag = false; //s = pq.Dequeue(); if (Sequence.Contains(s.StationID) == false) { Sequence[a] = s.StationID; break; } if (pq.Count == 0) { if (supplyStation.Count != 0) { s = supplyStation.Max(); supplyStation.Remove(s); } break; } } min = double.MaxValue; //下一站是需要貨物的可是你卻沒有貨ㄌ if (s.Declinebymin < 0) { //find truck lack of goods if (truck.CurrentGoods == 0 && supplyStation.Count != 0) { min = double.MaxValue; //find the nearest supply station for (int i = 0; i < supplyStation.Count; i++) { m = distanceMatrix[Sequence[a - 1], supplyStation.ElementAt(i).StationID]; if (min > m) { min = m; selected = i; } } temp[a] = truck.SupplyTruck(supplyStation.ElementAt(selected)); flag = true; Sequence[a] = supplyStation.ElementAt(selected).StationID; supplyStation.RemoveAt(selected); if (a != stations.Length - 1) { Sequence[a + 1] = s.StationID; } } if (flag == true) { time += distanceMatrix[Sequence[a - 1], Sequence[a]] / speed;//到下一站的時間點 totalDistance += distanceMatrix[Sequence[a - 1], Sequence[a]]; if (a != stations.Length - 1) { time += distanceMatrix[Sequence[a], Sequence[a + 1]] / speed;//到下一站的時間點 totalDistance += distanceMatrix[Sequence[a], Sequence[a + 1]]; temp[a + 1] = truck.PickupDelivery(truckcapacity / 2); cost += HoldingShortageSurplus(time, Sequence[a + 1], temp[a + 1], ref truck); } a += 2; } else { temp[a] = truck.PickupDelivery(truckcapacity / 2); cost += HoldingShortageSurplus(time, Sequence[a], temp[a], ref truck); } } else { //find truck full of goods if (truck.CurrentSpace == 0 && supplyStation.Count != 0) { //find the nearest supply station min = double.MaxValue; for (int i = 0; i < supplyStation.Count; i++) { m = distanceMatrix[Sequence[a - 1], supplyStation.ElementAt(i).StationID]; if (min > m) { min = m; selected = i; } } temp[a] = truck.SupplyTruck(supplyStation.ElementAt(selected)); flag = true; Sequence[a] = supplyStation.ElementAt(selected).StationID; supplyStation.RemoveAt(selected); if (a != stations.Length - 1) { Sequence[a + 1] = s.StationID; } } if (flag == true) { time += distanceMatrix[Sequence[a - 1], Sequence[a]] / speed;//到下一站的時間點 totalDistance += distanceMatrix[Sequence[a - 1], Sequence[a]]; if (a != stations.Length - 1) { time += distanceMatrix[Sequence[a], Sequence[a + 1]] / speed;//到下一站的時間點 totalDistance += distanceMatrix[Sequence[a], Sequence[a + 1]]; temp[a + 1] = truck.PickupDelivery(-truckcapacity / 2); cost += HoldingShortageSurplus(time, Sequence[a + 1], temp[a + 1], ref truck); } a += 2; } else { temp[a] = truck.PickupDelivery(-truckcapacity / 2); cost += HoldingShortageSurplus(time, Sequence[a], temp[a], ref truck); } } if (flag == false) { time += distanceMatrix[Sequence[a - 1], Sequence[a]] / speed;//到下一站的時間點 totalDistance += distanceMatrix[Sequence[a - 1], Sequence[a]]; a++; } } if (a >= totalStation) { a = totalStation - 1; } //因為上面最後一次部會做所以... if (flag == false && stations[Sequence[a - 1]].Declinebymin < 0 && time <= timehorizon) { temp[a - 1] = truck.PickupDelivery(truckcapacity / 2); cost += HoldingShortageSurplus(time, Sequence[a - 1], temp[a - 1], ref truck); } else if (flag == false && stations[Sequence[a - 1]].Surplusbymin > 0 && time <= timehorizon) { temp[a - 1] = truck.PickupDelivery(-truckcapacity / 2); cost += HoldingShortageSurplus(time, Sequence[a - 1], temp[a - 1], ref truck); } else { a--; } //全部跑完要回去depot if (a == totalStation - 1) { totalDistance += startTOvertex[Sequence[a]]; } else { //沒有跑完的車站繼續算成本 for (int b = 0; b < pq.Count; b++) { cost += HoldingShortageSurplus(timehorizon, pq.ElementAt(b).StationID, 0, ref truck); } } richTextBox.Text = "routing path is depot "; for (int i = 0; i < a + 1; i++) { richTextBox.Text += (Sequence[i] + " "); } double totalPandD = 0; richTextBox.Text += "\n" + "pickup & delivery amount: "; for (int i = 0; i < temp.Length; i++) { richTextBox.Text += temp[i].ToString() + " "; totalPandD += Math.Abs(temp[i]); } richTextBox.Text += "\n" + "********performance********"; richTextBox.Text += "\n" + "unsatisfied amount :" + cost; richTextBox.Text += ("\n" + "total distance is " + totalDistance); richTextBox.Text += "\n" + "Total pickup & delivery : " + totalPandD; }