C# 节约里程法实现

节约里程法的C#实现
节约里程法需求因素有三个:车辆容量 节点需求量 两两点对间最短距离
节约里程法具体原理不 做详述,此处采用清华大学出版社《运筹学》第四版(非本科生版)P536-P538页所所讲述算法实现;
如下图所示:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
具体代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace Save_Distance
{
   public class Save_Distance
    {
        //创建线路结构体,包含节约里程,起点,终点
        public struct path
        {
            public double save_diatance;
            public int head;
            public int tail;
        }
        //路径规划算法
        public static ArrayList find_path(double whole_capacity, ArrayList demand, double[,] minpath)
        {
            double real_capacity = whole_capacity;

            //对站点需求量进行预处理;如果该站点需求量大于车辆整车容量,则直接减去该整车容量;
            //  double capacity = 3;
            //将节点需求量数据保存到ArryList当中
            //  ArrayList demand = new ArrayList();
        //    demand.Add(0.6); demand.Add(2.6); demand.Add(12.3); demand.Add(3.4);
            int i, j;
            ArrayList route_result = new ArrayList();
            ArrayList planed_node = new ArrayList();
            /*
            double[,] minpath = new double[100, 100];
            minpath[0, 0] = 12; minpath[0, 1] = 3.6; minpath[0, 2] = 6.6; minpath[0, 3] = 13.6;
            minpath[1, 0] = 7.7; minpath[1, 1] = 21.7; minpath[1, 2] = 0.9;
            minpath[2, 0] = 3.7; minpath[2, 1] = 49.7;
            minpath[3, 0] = 8.7; 
            */
            //计算节约里程,将数据保存到struct path类型的ArryList当中
            ArrayList Save_distance = new ArrayList();

            for (i = 0, j = 0; minpath[i, 0] != 0; i++)
            {
                for (j = 0; minpath[i, j + 1] != 0; j++)
                {
                    path p;
                    p.head = i;
                    p.tail = i + j + 1;
                    p.save_diatance = (minpath[0, i] + minpath[0, i + j + 1] - minpath[i + 1, j]);
                    Save_distance.Add(p);
                }
            }
            //对Save_distance 按照save_distance进行递减排序;
            for (i = 0; i < Save_distance.Count; i++)
            {
                for (j = 0; j < Save_distance.Count - i - 1; j++)
                {
                    path x = (path)Save_distance[j];
                    path y = (path)Save_distance[j + 1];
                    path temp_jiedian;
                    if (x.save_diatance < y.save_diatance)
                    { temp_jiedian = (path)Save_distance[j]; Save_distance[j] = (path)Save_distance[j + 1]; Save_distance[j + 1] = temp_jiedian; }
                }
            }

            //寻找节约里程,将其保存到Arrylist 当中;
            //确保所有节点都被正确规划;
            while (planed_node.Count != demand.Count)
            {
                double capacity = real_capacity;
                ArrayList plan_path = new ArrayList();
                //如果当前还有未添加的单个节点,但此时线路全被删除完毕,则单独规划一条路径;                   
                if (Save_distance.Count == 0)
                {
                    for (i = 0; i < demand.Count; i++)
                    {
                        if (!planed_node.Contains(i))
                        {
                            planed_node.Add(i);
                            plan_path.Add(i);
                            route_result.Add(plan_path);
                            break;
                        }
                    }
                }
                else
                {
                    //寻找可能的起始线路(节约里程尽可能的大,且路线上下标满足节点要求);
                    foreach (path innitial in Save_distance)
                    {
                        if ((double)demand[innitial.head] + (double)demand[innitial.tail] < capacity)
                        {
                            plan_path.Add(innitial.head);
                            plan_path.Add(innitial.tail);
                            capacity -= ((double)demand[innitial.head] + (double)demand[innitial.tail]);
                            break;
                        }
                    }
                    //如果当前节点中未能找到初始路线,则表明当前所有的节点都应当单独设置为一条路径
                    if (plan_path.Count == 0)
                    {
                        for (i = 0; i < demand.Count; i++)
                        {
                            if (!planed_node.Contains(i))
                            {
                                ArrayList many_path = new ArrayList();
                                many_path.Add(i);
                                planed_node.Add(i);
                                route_result.Add(many_path);
                            }
                        }
                    }

                    else
                    {
                        //遍历所有节点;
                        //如果当前线路中有head或者tail中有一个值等于plan_path的头,并且该点需求量满足车辆容量限制,则将tail或者head添加到plan_path的头部
                        //如果当前线路中有head或者tail中有一个值等于plan_path的尾,则将tail或者head添加到plan_path的尾部
                        //一旦找到一条符合要求的,则需要重新回到起点,从头遍历;
                        int bianli = 0;
                        while (bianli < Save_distance.Count)
                        {
                            foreach (path temppath in Save_distance)
                            {
                                if (temppath.head == (int)plan_path[0] && !plan_path.Contains(temppath.tail) && (double)demand[temppath.tail] <= capacity)
                                {
                                    plan_path.Insert(0, temppath.tail);
                                    //获取尾部的需求量,更新车辆剩余容量;
                                    capacity -= (double)demand[temppath.tail];
                                    break;
                                }
                                else if (temppath.head == (int)plan_path[plan_path.Count - 1] && !plan_path.Contains(temppath.tail) && (double)demand[temppath.tail] <= capacity)
                                {
                                    plan_path.Add(temppath.tail);
                                    capacity -= (double)demand[temppath.tail];
                                    break;
                                }
                                else if (temppath.tail == (int)plan_path[0] && !plan_path.Contains(temppath.head) && (double)demand[temppath.head] <= capacity)
                                {
                                    plan_path.Insert(0, temppath.head);
                                    capacity -= (double)demand[temppath.head];
                                    break;
                                }
                                else if (temppath.tail == (int)plan_path[plan_path.Count - 1] && !plan_path.Contains(temppath.head) && (double)demand[temppath.head] <= capacity)
                                {
                                    plan_path.Add(temppath.head);
                                    capacity -= (double)demand[temppath.head];
                                    break;
                                }
                            }
                            bianli += 1;
                        }
                        //将所有节点添加到已规划节点中;
                        foreach (int node in plan_path)
                        {
                            planed_node.Add(node);
                        }
                        route_result.Add(plan_path);
                        //找出一条线路后,删除已经不可能的线路;
                        for (i = 0; i < plan_path.Count; i++)
                        {
                            for (j = 0; j < Save_distance.Count; j++)
                            {
                                path temp = (path)Save_distance[j];
                                if (temp.head == (int)plan_path[i] || temp.tail == (int)plan_path[i])
                                {

                                    Save_distance.Remove(temp);
                                    j -= 1;
                                }
                            }
                        }
                    }
                }
            }

            foreach (ArrayList my_path in route_result)
            {
                foreach (int node in my_path)
                {
                    Console.WriteLine(node);
                }
                Console.WriteLine("another");
            }
            Console.WriteLine("结束");

            return route_result;
        }
        static void Main(string[] args)
        {
            // find_path();
            Console.ReadLine();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/zhangxiaojiakele/article/details/70176943