剑offer - 4 - 动归

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()];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值