闭环最短路径算法

适用于闭环状态下各节点间距相等,计算从其中一个节点去1个或多个目标节点的最短路径,最短路径可以折返取得。

下面是一个有着10000个节点的闭环,从其中一个节点去往9个目标节点的示例。

static void Main(string[] args)
{
    int x = 3;//起点
    int[] arr = { 2, 2000, 4900, 9990, 6001, 200, 400, 80, 60 };//目的地
    int pe = 10000;//全周总步进
    int[] pathArr = ShortestPath(x, arr, pe);
    Console.WriteLine(string.Join(",",pathArr));
}


static int[] ShortestPath(int x, int[] goalArr, int perim)
{
    List<int> aList = goalArr.Where(p => p != x && p >= 1 && p <= perim).ToList();
    if (!aList.Any()) return null;
    //最大折返步进数(折返步进数的3倍小于等于1/2总周步进,折返才可能存在最优路径。)
    int bl = (int)Math.Floor(perim / 6m);
    int a = x;
    int b = x;
    int c = x - bl < 1 ? perim + x - bl : x - bl;
    int d = x + bl > perim ? x + bl - perim : x + bl;         


    IEnumerable<int> aIE = new int[] { x };
    IEnumerable<int> bIE = new int[] { x };
    IEnumerable<int> cIE = new int[] { };
    IEnumerable<int> dIE = new int[] { };
    //如在双向最大折返步进内存在目的地,取双向最远折返点到起点之间的步进
    for (int i = 0; i < bl ; i++)
    {
        if (cIE.Any() || aList.Contains(c)) cIE = (new int[] { c }).Concat(cIE);
        if (dIE.Any() || aList.Contains(d)) dIE = (new int[] { d }).Concat(dIE);
        c = c + 1 > perim ? 1 : c + 1;
        d = d - 1 < 1 ? perim : d - 1;
    }
    cIE = (new int[] { x }).Concat(cIE);
    dIE = (new int[] { x }).Concat(dIE);
    c = cIE.Last();
    d = dIE.Last();


    List<int> cList = aList.Where(p => !cIE.Contains(p)).ToList();
    if (!cList.Any()) return cIE.ToArray();
    List<int> dList = aList.Where(p => !dIE.Contains(p)).ToList();
    if (!dList.Any()) return dIE.ToArray();
    List<int> bList = aList.GetRange(0, aList.Count);


    for (int i = 1; i < perim; i++)
    {
        a = a + 1 > perim ? 1 : a + 1;
        b = b - 1 < 1 ? perim : b - 1;
        c = c + 1 > perim ? 1 : c + 1;
        d = d - 1 < 1 ? perim : d - 1;
        aIE = aIE.Concat(new int[] { a });
        if (aList.Contains(a))
        {
            aList.Remove(a);
            if (!aList.Any()) return aIE.ToArray();
        }
        bIE = bIE.Concat(new int[] { b });
        if (bList.Contains(b))
        {
            bList.Remove(b);
            if (!bList.Any()) return bIE.ToArray();
        }

        if (cList.Any()) cIE = cIE.Concat(new int[] { c });
        if (cList.Contains(c)) cList.Remove(c);
        if (!cList.Any() && cIE.Count() < dIE.Count()) return cIE.ToArray();

        if (dList.Any()) dIE = dIE.Concat(new int[] { d });
        if (dList.Contains(d)) dList.Remove(d);
        if (!dList.Any() && dIE.Count() < cIE.Count()) return dIE.ToArray();
    }
    return null;
}


©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值