256.房子涂色
*解题思路:
房子i的最小涂色开销是房子i-1的最小涂色开销,加上房子i本身的涂色开销。但是房子i的涂色方式需要根据房子i-1的涂色方式来确定,所以我们对房子i-1要记录涂三种颜色分别不同的开销,这样房子i在涂色的时候,我们就知道三种颜色各自的最小开销是多少了。我们在原数组上修改,可以做到不用空间。
State: dp[i][j] // three colors: j = 0 or 1 or 2,
Function:
dp[i][0] = dp[i][0] + min(dp[i - 1][1], dp[i -1][2])
dp[i][1] = dp[i][1] + min(dp[i - 1][0], dp[i - 1][2])
dp[i][2] = dp[i][2] + min(dp[i - 1][0], dp[i - 1][1])
Initialize: dp = costs
Return: min(dp[n][0], dp[n][1], dp[n][2])
#include<bits/stdc++.h>
using namespace std;
void fun(vector<vector<int>>& costs){
int size = costs.size();
vector<vector<int>>dp = costs;
for(int i=1;i<size;i++){
dp[i][0] = dp[i][0] + min(dp[i-1][1], dp[i-1][2]);
dp[i][1] = dp[i][1] + min(dp[i-1][0], dp[i-1][2]);
dp[i][2] = dp[i][2] + min(dp[i-1][0], dp[i-1][1]);
}
cout<<min(dp[size-1][0], min(dp[size-1][1], dp[size-1][2]));
}
int main(){
vector<vector<int>> costs = {{14,2,11},{11,14,5},{14,3,10}};
fun(costs);
}
47.礼物最大价值
在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
示例 1:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 12
解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物
感想:改造原有矩阵节省空间且易于理解,但边界初始化要细心:
class Solution {
public:
int weight = 0;
int m,n;
int maxValue(vector<vector<int>>& grid) {
m = grid.size()-1;
n = grid[m].size()-1;
if(m==0 && n == 0) return grid[m][n];
//边界初始化要细心
for(int i=0;i<=m;i++){
for(int j=0;j<=n;j++){
if(i == 0 && j == 0) continue;
//边界初始化要细心
if(i == 0) grid[i][j] = grid[i][j-1]+grid[i][j];
//边界初始化要细心
else if(j == 0) grid[i][j] = grid[i-1][j]+grid[i][j];
else grid[i][j] = max(grid[i-1][j],grid[i][j-1])+grid[i][j];
cout<<"i "<<i<<" -- j "<<j<<"="<<grid[i][j]<<endl;
}
}
return grid[m][n];
}
};
42.连续子序列的和同LC53
初始化很重要。
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int size = nums.size();
if(size == 0) return 0;
vector<int> dp(size,0);
dp[0] = nums[0];
int result = nums[0];
for(int i=1;i<size;i++){
dp[i]=dp[i-1]>0?nums[i]+dp[i-1]:nums[i];
if(dp[i]>result) result = dp[i];
}
return result;
}
};
LC53
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size()==0) return 0;
if(nums.size()==1) return nums[0];
int max=nums[0];
for(int i=1;i<nums.size();i++){
nums[i]=nums[i-1]>0?nums[i-1]+nums[i]:nums[i];
if(nums[i]>max) max = nums[i];
}
return max;
}
};
91.编码
注意,字符串是从第二个字符串开始审查的,但是dp数组需要用到dp[i-2]和dp[i-1]所以要先初始化dp[0]和dp[1],因此dp要比s往后多一个数字:
class Solution {
public:
int numDecodings(string s) {
if(s.size() == 0 ||s[0]=='0') return 0;
vector<int> dp(s.size()+1);
dp[0]=1;dp[1] = 1;
for(int i=1;i<s.size();i++){
if(s[i] == '0'){
if(s[i-1]=='1'||s[i-1]=='2'){
dp[i+1] = dp[i-1];
cout<<"here1"<<endl;
}
else return 0;
}else{
int temp=(s[i-1]-'0')*10+(s[i]-'0');
if(temp>=10 && temp<=26) {
cout<<"here2"<<endl;
dp[i+1] = dp[i]+dp[i-1];
}
else {
cout<<"here3"<<endl;
dp[i+1] = dp[i];
}
}
}
return dp[s.size()];
}
};