相比LeetCode 198. House Robber, 由于题目将整个房子变成了一个环形,我们在此就多增加了一维k, 用来专门标识是否取nums[0].
应用动态规划,构造数组dp[nums.size()][2][2], 对于dp[i][j][k],
j=0时不取nums[i], j=1时取nums[i];
k=0时不取nums[0], k=1时取nums[0].
所以dp[i][0][0]即代表,在不去nums[i]和nums[0]的情况下,从nums[0, ..., i]中取得的最大值。
初始化:
// for stage-0
dp[0][1][1] = nums[0];
// for stage-1
dp[1][0][1] = nums[0];
dp[1][1][0] = nums[1];
注意到dp[0][0][1]和dp[1][1][1]都是不合法的特殊情况:如对于dp[1][1][1], 我们不可能同时取第0个和第1个元素(房子里的财产),所以我们将它的值赋为0, 不进行特殊的初始化。
代码:
class Solution { public: int rob(vector<int>& nums) { if (nums.empty()) { return 0; } else if (nums.size() == 1) { return nums[0]; } else if (nums.size() == 2) { return max(nums[0], nums[1]); } // i: nums index, j: self taken or not, k: nums[0] taken or not vector<vector<vector<int>>> dp(nums.size(), vector<vector<int>>(2, vector<int>(2, 0))); // for stage-0 dp[0][1][1] = nums[0]; // for stage-1 dp[1][0][1] = nums[0]; dp[1][1][0] = nums[1]; for (size_t i = 2; i < nums.size(); ++ i) { dp[i][0][0] = max(dp[i-1][0][0], dp[i-1][1][0]); dp[i][0][1] = max(dp[i-1][0][1], dp[i-1][1][1]); dp[i][1][0] = dp[i-1][0][0] + nums[i]; dp[i][1][1] = dp[i-1][0][1] + nums[i]; } return max(max(dp[nums.size()-1][0][0], dp[nums.size()-1][0][1]), dp[nums.size()-1][1][0]); } };