【问题标题】:Generate all paths through matrix with max N similarity to any other生成通过矩阵的所有路径,与任何其他路径具有最大 N 相似度
【发布时间】:2012-03-30 23:25:53
【问题描述】:

我有一个 X 乘 Y 矩阵,我需要从中生成从一侧(第一列)到另一侧(最后一列)的所有可能方式,但途中只有 N 个点可以是与任何其他生成的组合相同。

我知道我可以生成所有组合并将它们与所有其他组合进行比较以过滤掉我想要的组合,但是对于像 16 x 16 这样的更大矩阵,组合是一种很多种方式来生成它们并将每个组合与休息。

有没有一种方法可以生成具有最大 N 相似度的组合,而不必全部生成?

示例:N=1

["a", "a", "a"]
["b", "b", "b"]
["c", "c", "c"]

应该生成如下内容: 啊啊啊 abb ACC 巴巴 cca 出租车

我已经研究了几天了,还没有找到任何好的解决方案,所以非常感谢任何帮助,如果可能的话,在 C# 中。

【问题讨论】:

  • 请解释“我需要生成所有可能的方式从一侧到达另一侧”。你的意思是从边缘的单元格到对边?
  • 抱歉不清楚,是的,我的意思是从第一列到最后一列。
  • 那么你的第二条路径应该是abbb而不是abb。不? abccc,bbb,bccc,ccc,cbbb,cbaaa,abbcc,cbbaa,我明白了吗?
  • 路径只能通过1-2-3列,所以长度不能超过3个字符
  • 我放弃了;问题中没有解释太多东西。随意修改它,我会重新访问。一个更好的例子和解释会有所帮助。也许发布你的整个作业问题而不是解释它。

标签: c# matrix path


【解决方案1】:

答案 = y ^ (x - n)

首先忽略您的问题,概括地说,您有一个 3x3 网格。所以:

x = 3;
y = 3;
n = 1;

因此你有 y^x 组合,即 3^3 = 27

如果您想确保一路上没有一定数量的匹配,您可以简单地将列的数量减少该数量,以减少排列的数量。

在您的示例中,N 为 1,因此将 x 减 1 以得到 x 为 2。

现在 3^2 = 6,这是你给出的答案。

如果你要扩大规模,我相信它会是准确的,但我已经度过了漫长的一周,所以如果我错过了什么,请随时告诉我。

编辑 重新阅读您的问题后,我不确定我是否理解正确,我很感兴趣,所以请告诉我...

【讨论】:

  • 我认为他需要实际生成正确的路径;但知道有多少(如果准确的话)可以帮助他早日逃脱。
  • 是的,重读后我也有这样的印象。基本上想要不共享许多字母的 x 字母的每个组合。看起来像家庭作业!
【解决方案2】:

我不确定如何立即降低空间复杂度,但是,您可以使用动态编程来避免检查重复项,从而降低时间复杂度。通过一些额外的努力,通常也可以降低动态规划问题的空间复杂度。

存在一个最优子结构,因为路径只是独立但重叠的前缀的总和(a+a = aa,aa+a = aaa)。考虑到这一点,我们可以通过以下方式解决 3x3 的问题。

纸笔法:

已确定第一选择的解决方案 - a、b、c。 我们需要确定第二选择、第三选择等的解决方案。

通过连接 row + col 确定两个前缀 - 两列可用的选项。

a b c 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 b ba bb bc c ca cb cc

获取我们刚刚创建的前缀并将它们应用于我们最初的 1x1 解决方案 - row + col

a b c 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 咩咩咩咩 ca caa 出租车 cac ab aba abc bb bba bbb 英国广播公司 cb cba cbb cbc ac aca acb ac bc bca bcb bcc cc cca ccb ccc

n*n 解决方案就是这种方法重复 n-1 次。

我也是用 C# 写出来的

class Program
{
    static void Main(string[] args)
    {
        int sizeOf = 3; //size of problem - ex 3x3
        var vals = "abcdefghijklmnop".ToCharArray(); //up to 16 (abc in ex)

        //Create initial problem
        String[] x = new String[sizeOf]; 
        String[] y = new String[sizeOf];

        for (int i = 0; i < x.Length; i++)
        {
            x[i] = vals[i].ToString();
            y[i] = vals[i].ToString();
        }

        //hold our solutions
        String[][] result = null;
        String[] temp = x;

        for (int i = 1; i < y.Length; i++)
        {
            result = getCombos(temp, y);

            temp = (from k in result
                    from l in k
                    select l).ToArray();
        }

        //Flatten out solution
        var finalResult = (from k in result
                           from l in k
                           select l).ToList();

        printArray(finalResult);
        Console.WriteLine("Total Count: {0}", finalResult.Count());

    }

    static void printArray(List<String> a)
    {
        foreach (var x in a)
        {
            Console.Write("{0} ", x);
        }
        Console.WriteLine();
    }

    static String[][] getCombos(String[] x, String[] y)
    {
        //Initialize array to hold solution
        String[][] prefixes = new String[x.Length][];
        for (int j = 0; j < x.Length; j++)
        {
            prefixes[j] = new String[y.Length];
        }

        //concat to form solution
        for (var i = 0; i < x.Length; i++)
        {
            for (var j = 0; j < y.Length; j++)
            {
                prefixes[i][j] = x[i] + y[j];
            }
        }
        return prefixes;
    }
}

在空间复杂度变得太多之前,我将它运行到了 9x9。这是一个非常有趣的问题。

【讨论】:

  • 感谢您的帮助,一个非常好的解决方案,将其保存以供将来的项目使用。我只需要 16x16 中的大约 500k 个组合,所以我最终随机选择了这些组合,并根据哈希矩阵检查它们,其中包含在该位置具有当前字符的所有其他组合的列表。这样做我不必检查所有其他组合,只需检查可能的匹配项,并在我不在的周末完成我的 500k。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-29
  • 1970-01-01
  • 2017-10-30
  • 2021-01-04
  • 2014-08-28
  • 1970-01-01
相关资源
最近更新 更多