动态规划经典入门级题目*2及详解

来源:互联网 发布:韩智慧知乎 编辑:程序博客网 时间:2024/06/05 15:21

题目来自极客学院的视频教程-动态规划(一)

一句话解释动态规划:多阶段最优化决策解决问题的过程

解题技巧:只关注状态转移(子问题之间的关系),不要考虑某个状态是怎么出现的


1.字符串解码

一个只包含大写字母的字符串加密后变成了只包含数字的字符串,加密的规则:

'A' -> 1

'B' -> 2

...

'Z' -> 26

现在给定一个只包含数字的加密过的字符串,求该字符串有多少种解密的方法。例如“12”->"AB", "12"->"L"


解:2位的在26以内的相邻的数可以产生不同的解,字符串用str表示,用一维数组dp[i]来表示从0到i位解码方法总数,dp[0]=1,想从dp[i]得到dp[i+1]:

1.str[i+1]是‘0’,那么他不能单独译成一个字母,一定是和str[i]组合,dp[i+1] = dp[i-1]

2.str[i+1]不是‘0’:  

   1)str[i]和str[i+1]位不能组成一个字母,将str[i+1]解码为对应的字母,dp[i+1] = dp[i]

   2)str[i]和str[i+1]可以组和译成一个字母,则在这里就可以出现2种解码方法,如果单独译dp[i+1],有dp[i]种方法,如果组合起来,有dp[i-1]种方法,那么dp[i+1] = dp[i]+dp[i-1]

代码:

int Decode_num(string& str) {    int len = str.length();    int *dp = new int[len];    dp[0] = 1;    if (str[1] == '0') dp[1] = 1;    else if (str[0] == '1' || (str[0] == '2' && str[1] <= '6')) dp[1] = 2;    else dp[1] = 1;    for (int i = 1; i < len-1; i++) {if (str[i+1] == '0') dp[i+1] = dp[i-1];        else if (str[i] == '1' || (str[i] == '2' && str[i+1] <= '6')) dp[i+1] = dp[i] + dp[i-1];        else dp[i+1] = dp[i];    }    return dp[len-1];}


2.最大子数组乘积

给定一个整数数组,求乘积最大的子数组的乘积值


解:

1)首先明确数组中的数可能是负数

2)设数组是vec[],这里我们在for循环中用一个max和min值分别记录包含0~i中包含vec[i]的子数组的乘积的最大值和最小值,为什么一定是包含vec[i]呢,因为只有在这个定义之下,我们才能由i计算到i+1

3)那么包含vec[i]的子数组乘积的最大值就是vec[i],vec[i]*max,vec[i]*min中的最大值(当min和vec[i]同为负,相乘得到最大值),更新max值

4)循环中同时更新min,min就是vec[i],vec[i]*max,vec[i]*min中的最小值

5)返回的结果max_product,是以0~size-1结尾的子数组乘积最大值的最大值

代码:

int Max_product(vector<int>& vec) {    int size = vec.size();    int max_product = vec[0];    int _min = vec[0];    int _max = vec[0];    for (int i = 1; i < size; i++) {        int copy_max = _max;        _max = max(max(vec[i], vec[i]*_max), vec[i]*_min);        _min = min(min(vec[i], vec[i]*_min), vec[i]*copy_max);        max_product = max(max_product, _max);    }    return max_product;}



原创粉丝点击