动态规划-线性模型

一、动态规划简介
  1. 动态规划可以用一句话概括:

动态规划是在解决多阶决策的过程中动态地选择最优决策的方法

  1. 最终目的:找出最优解
  2. 问题特征:
    (1). 问题范围可以缩小到多个问题单元,对应多种决策
    (2). 这多个决策动态选择组合可以充分解决整个问题
  3. 解决问题三要素:
    (1). 最优子决策
    (2). 边界值
    (3). 状态抉择公式
二、线性模型

例子:小朋友过桥
四个调皮的小朋友晚上要过桥去对岸玩耍。桥一次最多只能通过两个小朋友,他们只有一个手电筒,过桥需要有人拿着手电筒,问他们怎么过最快。其中这四个小朋友的过桥速度分别为1,2,5,10 (分钟)
在这里插入图片描述

有的人会想到贪心算法(只要一个策略作为最优策略):速度最快的小朋友来回传手电筒,那么有什么欠考虑的地方呢?我们一起来看一下过程图:
贪心算法过程图
【贪心算法过程图】
在这里插入图片描述
【动态规划过程图】
图1算出19,图2算出17,相信你已经发现,一起走的两个人,如果速度相当,反而会节约时间。如果你害怕还有欠考虑的情况,那就直接用动态规划思路吧,一起来看看。

三、动态规划步骤(自底向上):

先将小朋友按照速度快慢进行排列得到队列:
t[i]={t(1),t(2),t(3)…t(i)}
1.找出边界
最后剩下两个小朋友、最后剩下1个小朋友
2.找出边界对应最优子决策
最后剩下1个小朋友:
remainOne(i)=sum(i)=sum(i-1)+t(1)+t(i)
最后剩下两个小朋友:
remainTwo(i)=sum(i)=sum(i-2)+t(1)+t(i)+t(2)+t(2)
3.状态抉择
sum(i)=min(remainOne(i),remainTwo(i))

四、送上完整java实现代码
public class AlgorithmTest {
    public static int[] childTimes=new int[]{1,2,5,10};//{2,4,5,7};

    public static int indexFirst=0;
    public static int indexSecond=1;
    public static void main(String[] args) {
        AlgorithmTest test=new AlgorithmTest();
        System.out.println(test.getSumTime(4-1));
        System.out.println(test.getSumTimeFor());
    }

    //递归方式
    public int getSumTime(int i) {
        if (i <=indexSecond) {
            if(childTimes.length==1){
                return childTimes[indexFirst];
            }
            return childTimes[indexSecond];
        }
        //如果只剩下一个,那么总耗时=i-1个人之前的总耗时+一个来回(送电筒的+最后一个的)
        int lastone = getSumTime(i - 1) + childTimes[indexFirst] + childTimes[i];
        int lasttwo = getSumTime(i - 2) + childTimes[indexFirst] + childTimes[i] + childTimes[indexSecond] + childTimes[indexSecond];
        return Math.min(lastone, lasttwo);
    }

    //备忘录方式
    public int getSumTimeFor(){
        int[] memoMin=new int[childTimes.length];
        int memoRemainOne=0;
        int memoRemainTwo=0;
        int n=childTimes.length-1;
        if (n ==indexFirst||n==indexSecond) {
            if(childTimes.length==1){
                memoMin[0]= childTimes[indexFirst];
            }
            memoMin[0]= childTimes[indexSecond];
            return memoMin[0];
        }
        
        memoMin[0]=memoMin[1]= childTimes[indexSecond];
        for (int i=2;i<=n;i++){
            memoRemainOne=memoMin[i-1] + childTimes[indexFirst] + childTimes[i];
            memoRemainTwo=(memoMin[i-2])+ childTimes[indexFirst] + childTimes[i] + childTimes[indexSecond] + childTimes[indexSecond];
            memoMin[i]=Math.min(memoRemainOne, memoRemainTwo);
        }
        return memoMin[n];
    }
}

最后输出:

17
17

集合为{2,4,5,7}则输出:

20
20
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值