动态规划系列:1.基础

1 使用动态规划求解问题的特点:


  1. 求解问题的最优解(最大值或者最小值)

  1. 这个问题可以分解成若干个子问题,整体问题的最优解依赖各个子问题的最优解

  1. 这些小问题间还有相互重叠的更小的子问题

  1. 从上往下分析问题,从下往上求解问题,这是动态规划解决问题的第四个特点,在第2节说明

例子:长度为n的绳子剪成m段(n>1且m>1且m,n都为整数),各段长度的乘积可能最大值是多少。

满足:特点一:求剪出各段绳子长度乘积的最大值,满足特点一

特点二:用f表示剪后的最大值,问题为求f(n),任意位置如i剪一刀,因为f(n)=f(i)*f(n-i),问题变为求两个子问题,满足第二个特点

特点三:如果n=10,最初在4剪一刀,然后4绳子中间剪一刀,6绳子剪为2和4,问题变为:

f(10)=f(4)*f(6)=[f(2) * f(2)]*[f(2) * f(4)]

则f(4)和f(6)存在重叠子问题f(2)

特点四:由于子问题在分解大问题过程重复出现,为避免重复求解,从下往上求解小问题并存储下来,以此为基础求解大问题

2 动态规划算法步骤


  1. 判断题目是否是动态规划可以求解的题目:题目是否有以下几个特性:

(1) 能否将问题分解为几个子问题

(2)子文提是否可以往下划分,是否有重叠子问题

(3)有的题目是有关键字:“多少种”,“最”

  1. 将题目抽象出来,用f(n)表示该问题的(最优)解,根据划分的子问题写出f(n)=.......(递推关系)

  1. 由下往上求解,设计循环,从f(0),f(1),...开始求解

  1. 返回f(n)

以上面题目为例,

注意区分,长度为2、3的绳子与将一段绳子分解到长为2、3子问题的区别

代码:

int maxProductAftercut(int length) {
    if (length < 2) return 0;//题目要求至少剪一刀,剪不了
    if (length == 2) return 1;//剪一刀最大乘积为1
    if (length == 3) return 2;//剪若干段最大乘积为2

    //定义存储数组
    int *record = new int[length + 1];//0,1,2,3...,length
    //record[i]表示长度为i的绳子被剪成若干段后的各段绳子乘积可能最大值

    record[0] = -1;//用不到
    record[1] = 1;//1为单位长度
    record[2] = 2;//分解到长度为2,3的绳子的小问题,不剪才是最大值
    record[3] = 3;
    for (int i = 4; i <= length; i++) {//对长度为i的绳子
        //开始剪
        int max = 0;
        for (int j = 1; j <= i / 2; j++) {
            int tmp = record[j] * record[i - j];
            if (tmp > max) max = tmp;
        }
        record[i] = max;
    }
    int max = record[length];
    delete[] record;
    return max;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值