在二进制矩阵中查找最低成本

时间:2013-06-24 08:18:34

标签: algorithm graph graph-coloring

考虑一个n * n二进制矩阵。该矩阵的每个单元最多具有4个邻居(如果存在)。如果它们是邻居并且它们的值不相等,我们称该矩阵的两个单元不兼容。我们为每个不兼容的货币对支付$ b。我们也可以通过支付$ a来更改单元格的值。

问题是要找到此矩阵的最低成本。

我已经使用了回溯并找到了O(2 ^ (n * n))的算法。有人可以帮我找到更有效的算法吗?

2 个答案:

答案 0 :(得分:12)

这个想法归功于Greig,Porteous和Seheult。将矩阵视为带有效的有向图,其顶点对应于矩阵条目和从每个顶点到其四个邻居的弧,每个邻居具有容量 b 。引入另外两个顶点,一个源和一个接收器,以及容量为 a 的弧:从源到每个顶点,对应的0条目,以及从每个顶点到相应的1个条目的接收器。找到最小切口;更改后值为0的条目是剪切源侧的顶点,更改后值为1的条目是剪切池侧的顶点。

这次削减的成本正是你的目标。在容量 - a 来自源弧的情况下,穿过切口的那些对应于从0到1的变化。在容量 - a 到 - 吸收弧的过程中,切割对应于从1到0的变化。在容量 - b 弧中,穿过切口的弧对应于从0到1的弧的实例。

答案 1 :(得分:0)

我建议你重新制定你的回溯,以便使用动态编程来修剪回溯树。以下是我建议设计它的逻辑:

在决定是否要更改单元格时,分配前一个单元格的方式并不重要,只关注累计成本,因此您可以跟踪每个单元格以及每个可能的累计成本,已找到的最低结果是什么。这样,无论何时再次找到相同的配置,您都将保存答案。

所以你的dp矩阵会是这样的:

dp[top_bound][n][n];

在做回溯之前,你应该这样做:

if(dp[acc_cost][this_i][this_j] != -1)
    return dp[acc_cost][this_i][this_j];

// Perform your calculations
// ...

dp[acc_cost][this_i][this_j] = result;
return result;

这里我假设-1是结果中的无效值,如果不是,您只需选择任何无效值并将矩阵初始化为它。由于此矩阵的大小为n * n * top_bound,因此正确实现的DP应解决O(n * n * top_bound)中的问题。