首页 > 其他 > 详细

6.动态规划

时间:2021-03-30 00:24:38      阅读:23      评论:0      收藏:0      [点我收藏+]
/*
动态规划
    动态规划和其它遍历算法(如深/广度优先搜索)都是将原问题拆成多个子问题然后求解,他们之间的最本质区别是,动态规划保存子问题的解,避免重复计算。
解决动态规划问题的关键是找到状态转移方程,这样我们可以通过计算和存储子问题的解来求解最终问题。

状态转移矩阵及dp数组初始化
*/


//70.爬楼梯
/*
题目描述:给定n节台阶,每次可以走一步或两步,求一共有多少种方式可以走完这些台阶。
输入输出样例:输入是一个数字,表示台阶数量;输出是爬台阶的总方式。
Input:3  Output:3
在这个样例中,一共有三种方法走完这三节台阶;每次走一步;先走一步,再走两步;先走两步,再走一步。
题解:这是十分经典的斐波那契数列问题。定义一个数组dp,dp[i]表示走到第i阶的方法数。因为我们每次可以走一步或者两步,所以第i阶台阶可以从第i-1或i-2阶
到达。换句话说,走到第i阶的方法数即为走到第i-1阶的方法数加上走到第i-2阶的方法数。这样我们就得到了状态转移方程dp[i]=dp[i-1]+dp[i-2]。注意边界条件
的处理。
*/
int climbStairs(int n){
    if(n<2) return n;
    vector<int> dp(n+1, 1);
    for(int i=2; i<=n; i++){
        dp[i]=dp[i-1]+dp[i-2];
    }
    return dp[n];
}


//198.打家劫舍
/*
题目描述:假如你是一个劫匪,并且决定抢劫一条街上的房子,每个房子内的钱财数量各不相同。如果你抢了两栋相邻的房子,则会触发警报机关。求在不触发机关的情况下
最多可以抢劫多少钱。
输入输出样例:输入是一个一维数组,表示每个房子的钱财数量;输出是劫匪可以最多抢劫的钱财数量。
Input:[2,7,9,3,1]  Output:12   在这个样例中,最多的抢劫方式为抢劫第1、3、5个房子
题解:定义一个数组dp,dp[i]表示抢劫到第i个房子时,可以抢劫的最大数量。我们考虑dp[i],此时可以抢劫的最大数量有两种可能,一种是我们选择不抢劫这个房子,此时
累计的金额即为dp[i-1];另一种是我们选择抢劫这个房子,那么此前累计的最大金额只能是dp[i-2],因为我们不能够抢劫第i-1个房子,那么此前累计的最大金额只能是dp[i-2],
因为我们不能够抢劫第i-1个房子,否则会触发警报机关。因此本题的状态转移方程为dp[i]=max(dp[i-1],nums[i-1]+dp[i-2]).
*/
int rob(vector<int>& nums){
    if(nums.empty()) return 0;
    int n=nums.size();
    vector<int> dp(n+1, 0);
    dp[1]=nums[0];
    for(int i=2; i<=n; i++){
        dp[i] = max(dp[i-1], nums[i-1]+dp[i-2]);
    }
    return dp[n];
}


//64.最小路径和
/*
题目描述:给定一个m*n大小的非负整数矩阵,求从左上角开始到右下角结束的、经过的数字的和最小的路径。每次只能向右或者向下移动。
输入输出样例:输入是一个二维数组,输出是最优路径的数字和。
Input:
[[1,3,1]
 [1,5,1]
 [4,2,1]]
Output:7
在这个样例中最优的路径为1->3->1->1->1.
题解:我们可以定义一个同样是二维的dp数组,其中dp[i][j]表示从左上角开始到(i,j)位置的最优路径的数字和。因为每次只能向下或者向右移动,我们可以很快容易得到
状态转移方程dp[i][j]=min(dp[i-1][j], dp[i][j-1])+grid[i][j],其中grid表示原数组。
*/
int minPathSum(vector<vector<int>>& grid){
    int m=grid.size(), n=grid[0].size();
    vector<vector<int>> dp(m, vector<int>(n, 0));
    for(int i=0; i<m; i++){
        for(int j=0; j<n; j++){
            if(i==0 && j==0){
                dp[i][j]=gird[i][j];
            }else if(i==0){
                dp[i][j]=dp[i][j-1]+grid[i][j];
            }else if(j==0){
                dp[i][j]=dp[i-1][j]+grid[i][j];
            }else{
                dp[i][j]=min(dp[i-1][j], dp[i][j-1])+gird[i][j];
            }
        }
    }
    return dp[m-1][n-1];
}


//221.最大正方形
/*
题目描述:给定一个二维数组的0-1矩阵,求劝由1构成的最大正方形面积。
输入输出样例:输入是一个二维0-1数组,输出是最大正方形面积。
Input:
[[1,0,1,0,0]
 [1,0,1,1,1]
 [1,1,1,1,1]
 [1,0,0,1,0]]
Output:4
题解:对于在矩阵中搜索正方形或长方形的题型,一种常见的做法是定义一个二维dp数组,其中dp[i][j]表示满足题目条件的、以(i,j)为右下角的正方形
或者长方形的属性。对于本题,则表示以(i,j)为右下角的全由1构成的最大正方形面积。如果当前位置(matrix中)是0,那么dp[i][j]即为0;如果当前
位置是1,那么dp[i][j]为相邻的左、右、左上三个点的最小值+1,那么状态转移方程为dp[i][j]=min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]))+1
*/
int maximalSquare(vector<vector<char>>& matrix){
    if(matrix.empty() || matrix[0].empty()){
        return 0;
    }
    int m = matrix.size(), n=matrix[0].size(), max_side = 0;
    vector<vector<int>> dp(m, vector<int>(n, 0));
    for(int i=0; i<m; i++){
        for(int j=0; j<n; j++){
            if(matrix[i][j] = 1){                 //如果是0,dp[i][j]就直接是0
                if(i==0 || j==0){
                    dp[i][j]=1;          //dp数组第一行初始化
                }else{
                    dp[i][j]=min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]))+1;
                }
            }
            max_side=max(max_side, dp[i][j]);
        }
    }
    return max_side*max_side;
}

 

6.动态规划

原文:https://www.cnblogs.com/go-ahead-wsg/p/14594457.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!