“房子用三色着色”是NP吗?
Posted
技术标签:
【中文标题】“房子用三色着色”是NP吗?【英文标题】:Is "house coloring with three colors" NP? 【发布时间】:2013-03-15 20:59:57 【问题描述】:考虑here 描述的问题(转载如下。)可以将一些更知名的NP完全问题简化为它吗?
问题:
有一排房子。每个房子都可以涂上三种颜色:红色、蓝色和绿色。用某种颜色粉刷每个房子的成本是不同的。你必须给所有的房子涂漆,这样相邻的两个房子就没有相同的颜色。你必须以最低的成本粉刷房屋。你会怎么做?
注意:将房子 1 涂成红色的成本与将房子 2 涂成红色的成本不同。房屋和颜色的每种组合都有其自身的成本。
【问题讨论】:
@Sudhanshu:在我的回答中:-) 您可以将其重申为最短路径问题的一个实例。每个房屋/颜色组合都是图中的一个顶点。表示相邻房屋的顶点连接在一起,除非它们具有相同的颜色。还有单独的开始和结束顶点。您现在可以为每条边分配成本并找到从起点到终点的最短路径。 @n.m. - 请您为您的提案添加一些伪代码,以通过带图方式的最短路径来解决它! 【参考方案1】:不,不是NP-hard(从技术上讲,“NP-complete”是错误的术语,因为这不是决策问题)。
Dynamic programming 有效,并为您提供 O(n) 时间算法。 (n 是房屋数量)。
您维护三个数组R[1..n], B[1..n], G[1..n]
,其中R[i]
是粉刷房屋1、2、3 ... i
的最低成本,因此i
是红色的。同样,B[i]
是绘制 1、2 ... i
的最低成本,i
被涂成蓝色,G[i]
是 i
被涂成绿色。
你可以计算R[i+1]
:
R[i+1]= (Cost of painting house i+1 Red) + minimum G[i], B[i]
。
同样可以计算B[i+1]
和G[i+1]
。
最终你至少会选择R[n], B[n] and G[n]
。
这是 O(n) 时间和 O(n) 空间。
例如考虑以下房屋的成本矩阵:
房屋编号:1 2 3 右:1 4 6 克:2 100 2 乙:3 100 4该算法正在构建以下矩阵以获得答案:
房屋:0 1 2 3 R:0 1 6 107 克:0 2 101 8 乙:0 3 101 10从最后一列中,我们可以找到所有 3 座房屋都被涂漆的最小成本,它等于 8,对应于组合 [Green (2), Red (4), Green (2)]。
快速 Python:
# rc = costs of painting red, bc of blue and gc of green.
def min_paint(rc, bc, gc):
n, i = len(rc), 1
r, b, g = [0]*n, [0]*n, [0]*n
r[0], b[0], g[0] = rc[0], bc[0], gc[0]
while i < n:
r[i] = rc[i] + min(b[i-1], g[i-1])
b[i] = bc[i] + min(r[i-1], g[i-1])
g[i] = gc[i] + min(b[i-1], r[i-1])
i += 1
return min(r, b, g)
def main():
print min_paint([1, 4, 6], [2, 100, 2], [3, 100, 4])
if __name__ == "__main__":
main()
输出将是 ([1, 6, 107], [2, 101, 8], [3, 101, 10]),这是一个导致解决方案的成本矩阵。
【讨论】:
它打印 ([1, 6, 107], [2, 101, 8], [3, 101, 10])。这说明了什么? 当然,更一般地说,这个解决方案不是 O(n),而是 O(n*c)。但是只指定了 3 种颜色,那就是 O(n)。无论哪种方式,都不是 NP 难题。 @user1247412 它是结果矩阵,如上面python中的代码所述。 @RichardPlunkett 不是 O(n*c^2) 吗?因为对于每种颜色,您还必须计算其他颜色的最小值,这是一个双for
循环 - 因此是 c^2。
解决方案在空间中不必是 O(n) - 不需要分析颜色分配的整个历史,我们只需要保留最后一列。当然,这会增加将“当前”列复制到“上一个”列的开销,但这仍然是 O(n) 时间,而内存使用量下降到 O(1)。【参考方案2】:
@Knoothe 的解释很中肯,但我相信实现可以改进 - 它使用 O(n)
额外空间来存储以前的值,但我们可以在 O(1)
空间中做到这一点,注意我们只需要每种颜色的前一个值,而不是整个值数组。方法如下:
def min_paint(rc, bc, gc):
# `r` is the min cost of painting the current house
# using color red; similarly for `b` and `g`
r, b, g = 0, 0, 0
for cr, cb, cg in zip(rc, bc, gc):
# new value for `r` is current cost for `r` plus the
# minimum cost for painting the previous house in one
# of the other two colors; similarly for `b` and `g`
r, b, g = cr + min(b, g), cb + min(r, g), cg + min(r, b)
# answer is the min cost for painting the last house
return min(r, b, g)
例如:
min_paint([1, 4, 6], [2, 100, 2], [3, 100, 4])
=> 8
【讨论】:
如果只需要最小成本值,这很好,但如果问题要求每个房屋的实际颜色值,您不能丢弃之前计算的 DP 值。以上是关于“房子用三色着色”是NP吗?的主要内容,如果未能解决你的问题,请参考以下文章