“房子用三色着色”是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吗?的主要内容,如果未能解决你的问题,请参考以下文章

如果房价暴跌,银行会没收你的房子吗?

做前端开发,30 岁前能买上房子吗?

2v1是np吗

我需要解决一个 NP 难题。有希望吗?

将房子卖了五百万,存在银行,靠利息能过日子吗?

老公年收入百万,却不愿拿出二十万帮我弟弟买房子,我该离婚吗?