Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 最近排列_C#_Algorithm_Permutation - Fatal编程技术网

C# 最近排列

C# 最近排列,c#,algorithm,permutation,C#,Algorithm,Permutation,目前,我有两个4个3D点的列表,我们称之为列表A和B。我想将A中的每个点连接到B中的一个(且仅一个)点,以使A和B之间的总距离最小化 例如,如果我有: A 1: (0,0,0) 2: (0,10,0) 3: (0,20,0) 4:(0,30,0) B 1: (0,35,10) 2: (0,25,10) 3: (0,15,10) 4:(0,5,10) 最佳解决方案是将A1与B4连接,A2与B3连接,A3与B2连接,A4与B1连接 如何以合理的方式进行计算?当项目数量较少时,如您的情况,您可以通过在

目前,我有两个4个3D点的列表,我们称之为列表A和B。我想将A中的每个点连接到B中的一个(且仅一个)点,以使A和B之间的总距离最小化

例如,如果我有:

A 1: (0,0,0) 2: (0,10,0) 3: (0,20,0) 4:(0,30,0)

B 1: (0,35,10) 2: (0,25,10) 3: (0,15,10) 4:(0,5,10)

最佳解决方案是将A1与B4连接,A2与B3连接,A3与B2连接,A4与B1连接


如何以合理的方式进行计算?

当项目数量较少时,如您的情况,您可以通过在三个嵌套循环中强制执行所有排列来实现这一点:

Point3D[] a = new Point3D[4];
Point3D[] b = new Point3D[4];
for (int i = 0 ; i != 4 ; i++) {
    for (int j = 0 ; j != 4 ; j++) {
        if (j == i) continue;
        for (int k = 0 ; k != 4 ; k++) {
            int m = 6 - i - j - k;
            if (k == i || k == j || m == i || m == j || m == k) continue;
            var d = a[0].Distance(b[i]) +a[1].Distance(b[j]) + a[2].Distance(b[k]) + a[3].Distance(b[m]);
            min = Math.Min(d, min);
        }
    }
}

这将在4中找到最小值!=24次迭代。如果您的点数超过,比如说,超过10个,则可以使用更好的算法-您可以使用查找多项式时间O(n3)中的最小权重匹配。

当项目数很小时,如您的情况,您可以通过在三个嵌套循环中强行执行所有置换来实现这一点:

Point3D[] a = new Point3D[4];
Point3D[] b = new Point3D[4];
for (int i = 0 ; i != 4 ; i++) {
    for (int j = 0 ; j != 4 ; j++) {
        if (j == i) continue;
        for (int k = 0 ; k != 4 ; k++) {
            int m = 6 - i - j - k;
            if (k == i || k == j || m == i || m == j || m == k) continue;
            var d = a[0].Distance(b[i]) +a[1].Distance(b[j]) + a[2].Distance(b[k]) + a[3].Distance(b[m]);
            min = Math.Min(d, min);
        }
    }
}


这将在4中找到最小值!=24次迭代。如果你的点数超过,比如说,超过10个,那么有一个更好的算法可用-你可以使用来在多项式时间O(n3)内找到最小权重匹配。

DP对我来说似乎是合理的:最简单的方法是使用蛮力,对于每个点,您计算a到所有b之间的距离,然后取最低的。@atoMerz DP对我来说似乎不太合理只有4!=24种可能性。试一试。DP对我来说似乎是合理的:最简单的方法是用蛮力,对于每个a点,你计算a到所有b点之间的距离,然后取最低的。@atoMerz DP对我来说似乎不太合理只有4!=24种可能性。试一下,这是错误的方法。尝试任何一个测试用例,其中a[0]应该与b[3]成对出现。有些人似乎非常喜欢触发here@dasblinkenlight-不。你能告诉我们为什么你删除了第一个被否决的答案,并用完全相同的答案创建了一个新答案吗?@SergeyS,因为被否决的选民错了。这其实是一个正确的答案,它只是有点小bugs@NiklasB. 我看到了编辑,我意识到我的评论是错误的。我把它删掉了。谢谢你的编辑!这是错误的做法。尝试任何一个测试用例,其中a[0]应该与b[3]成对出现。有些人似乎非常喜欢触发here@dasblinkenlight-不。你能告诉我们为什么你删除了第一个被否决的答案,并用完全相同的答案创建了一个新答案吗?@SergeyS,因为被否决的选民错了。这其实是一个正确的答案,它只是有点小bugs@NiklasB. 我看到了编辑,我意识到我的评论是错误的。我把它删掉了。谢谢你的编辑!这如何避免将一个点分配给其他几个点?请注意,我们需要一个不相交的匹配,每个a只连接到1个“是”,但a B可以连接到几个a'smissunderstood,在我看来,这一部分贪婪地将点分配给另一组中最接近的对应点。请参阅我对塞尔曼答案的评论,以了解该算法正确性的反例。这如何避免将一个点分配给其他几个点?请注意,我们需要一个不相交的匹配,每个a只连接到1个“是”,但a B可以连接到几个a'smissunderstood,在我看来,这一部分贪婪地将点分配给另一组中最接近的对应点。关于这个算法正确性的反例,请参阅我对塞尔曼答案的评论
    public static IEnumerable<T> Concat<T>(this T h, IEnumerable<T> t) {
        yield return h;
        foreach (var r in t) {
            yield return r;
        }
    }

    static IEnumerable<T> Reduce<T>(this IEnumerable<T> items, IEnumerable<T> collected, Func<T,T,bool> predicate) {
        if (!items.Any())
            return new T[0];

        var t = items.First();
        var filtered = items.Where(s => predicate(s,t));
        return t.Concat(filtered.Reduce(t.Concat(collected), predicate));
    }
struct Result {
    public Point A;
    public Point B;
    public double D;//distance
}

struct Point {
    public int X;
    public int Y;
    public int Z;
}

double DistanceTo(this Point a, Point b) {
    return Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y) + (a.Z - b.Z) * (a.Z - b.Z));
}