There are a row of n houses, each house can be painted with one of the three colors: red, blue or green. The cost of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent houses have the same color.
The cost of painting each house with a certain color is represented by a n x 3
cost matrix. For example, costs[0][0]
is the cost of painting house 0 with color red; costs[1][2]
is the cost of painting house 1 with color green, and so on... Find the minimum cost to paint all houses.
Note:
All costs are positive integers.
Example:
Input: [[17,2,17],[16,16,5],[14,3,19]] Output: 10 Explanation: Paint house 0 into blue, paint house 1 into green, paint house 2 into blue. Minimum cost: 2 + 5 + 3 = 10.
這道題說有n個房子,每個房子可以用紅綠藍三種顏色刷,每個房子的用每種顏色刷的花費都不同,限制條件是相鄰的房子不能用相同的顏色來刷,現在讓求刷完所有的房子的最低花費是多少。這題跟 House Robber II 和 House Robber 很類似,不過那題不是每個房子都搶,相鄰的房子不搶,而這道題是每個房子都刷,相鄰的房子不能刷同一種顏色,而 Paint Fence 那道題主要考察有多少種刷法。這幾道題很類似,但都不一樣,需要分別區分。但是它們的解題思想都一樣,需要用動態規划 Dynamic Programming 來做,這道題需要維護一個二維的動態數組 dp,其中 dp[i][j] 表示刷到第 i+1 房子用顏色j的最小花費,狀態轉移方程為:
dp[i][j] = dp[i][j] + min(dp[i - 1][(j + 1) % 3], dp[i - 1][(j + 2) % 3]);
這個也比較好理解,如果當前的房子要用紅色刷,則上一個房子只能用綠色或藍色來刷,那么要求刷到當前房子,且當前房子用紅色刷的最小花費就等於當前房子用紅色刷的錢加上刷到上一個房子用綠色和刷到上一個房子用藍色中的較小值,這樣當算到最后一個房子時,只要取出三個累計花費的最小值即可,參見代碼如下:
解法一:
class Solution { public: int minCost(vector<vector<int>>& costs) { if (costs.empty() || costs[0].empty()) return 0; vector<vector<int>> dp = costs; for (int i = 1; i < dp.size(); ++i) { for (int j = 0; j < 3; ++j) { dp[i][j] += min(dp[i - 1][(j + 1) % 3], dp[i - 1][(j + 2) % 3]); } } return min(min(dp.back()[0], dp.back()[1]), dp.back()[2]); } };
由於只有紅綠藍三張顏色,所以就可以分別寫出各種情況,這樣寫可能比上面的寫法更加一目了然一些,更容易理解一點吧:
解法二:
class Solution { public: int minCost(vector<vector<int>>& costs) { if (costs.empty() || costs[0].empty()) return 0; vector<vector<int>> dp = costs; for (int i = 1; i < dp.size(); ++i) { dp[i][0] += min(dp[i - 1][1], dp[i - 1][2]); dp[i][1] += min(dp[i - 1][0], dp[i - 1][2]); dp[i][2] += min(dp[i - 1][0], dp[i - 1][1]); } return min(min(dp.back()[0], dp.back()[1]), dp.back()[2]); } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/256
類似題目:
參考資料:
https://leetcode.com/problems/paint-house/
https://leetcode.com/problems/paint-house/discuss/68211/Simple-java-DP-solution