动态规划-房屋染色 II

文章介绍了一个关于房屋染色的问题,其中目标是寻找染色所有房子的最低成本。给定一个nxk的成本矩阵,表示每个房屋染不同颜色的费用,要求相邻房屋颜色不同。文章提供了两种解题思路,包括NKK时间和NK时间复杂度的解决方案,并给出了具体的动态规划代码实现。
摘要由CSDN通过智能技术生成

1 描述

这里有n个房子在一列直线上,现在我们需要给房屋染色,共有k种颜色。每个房屋染不同的颜色费用也不同,你希望每两个相邻的房屋颜色不同

费用通过一个nxk 的矩阵给出,比如cost[0][0]表示房屋0染颜色0的费用,cost[1][2]表示房屋1染颜色2的费用。找到油漆所有房子的最低成本。

所有费用都是正整数

2 样例

2.1 样例1

输入:
costs = [[14,2,11],[11,14,5],[14,3,10]]
输出: 10
说明:
三个屋子分别使用第1,2,1种颜色,总花费是10。

2.2 样例2

输入:
costs = [[5]]
输出: 5
说明:
只有一种颜色,一个房子,花费为5

2.3 挑战

用O(nk)的时间复杂度解决

3 题解

3.1 解题思路

3.1.1 时间复杂度NKK的方法

正常情况下,油漆前i栋房子并且房子i-1是颜色1,颜色2…颜色k的最小花费分别为f[i][0],f[i][1] … f[i][k-1]
f[i][0] = min{f[i - 1][1] + costs[i - 1][0], f[i - 1][2] + costs[i - 1][0], … ,f[i - 1][k - 1] + costs[i - 1][0]}
f[i][1] = min{f[i - 1][1] + costs[i - 1][1], f[i - 1][2] + costs[i - 1][1], … ,f[i - 1][k - 1] + costs[i - 1][1]}

f[i][k - 1] = min{f[i - 1][1] + costs[i - 1][k - 1], f[i - 1][2] + costs[i - 1][k - 1], … ,f[i - 1][k - 1] + costs[i - 1][k - 1]}

3.1.2 时间复杂度为NK的方法

时间复杂度缩减为NK的方法为首先先每次遍历第i - 1个房子的所有花费中的最小值和次最小值,如果当前的要染色和最小值的j值一致,则选择次最小值为最小值,如果不是则选择最小值作为当前染色的选项。

3.2 代码实现

  • 采用动态规划的方法处理
  • 时间复杂度为nk
  • 需要处理costs为空或者为1的特殊情况,其他的可以按照正常的处理流程来处理
class Solution {
public:
    /**
     * @param costs: n x k cost matrix
     * @return: an integer, the minimum cost to paint all houses
     */
    int minCostII(vector<vector<int>> &costs) {
        // write your code here
        int m = costs.size();
        if (m == 0) {
            return 0;
        }

        if (m == 1) {
            return costs[0][0];
        }

        int k = costs[0].size();
        int min1, min2;
        int id1 = 0, id2 = 0;
        vector<vector<int>> dp(m + 1);
        for (int i = 0; i <= m; i++) {
            dp[i].resize(k);
        }

        for (int i = 0; i < k; i++) {
            dp[0][i] = 0;
        }

        for (int i = 1; i <= m; i++) {
            min1 = min2 = INT_MAX;
            for (int j = 0; j < k; j++) {
                if (dp[i - 1][j] < min1) {
                    min2 = min1;
                    id2 = id1;
                    min1 = dp[i - 1][j];
                    id1 = j;
                } else {
                    if (dp[i - 1][j] < min2) {
                        min2 = dp[i - 1][j];
                        id2 = j;
                    }
                }
            }

            for (int j = 0; j < k; j++) {
                dp[i][j] = costs[i - 1][j];
                if (j != id1) {
                    dp[i][j] += min1;
                } else {
                    dp[i][j] += min2;
                }
            }
        }

        int res = INT_MAX;
        for (int i = 0; i < k; i++) {
            res = min(res, dp[m][i]);
        }

        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值