动态规划

备注:给小组人员讲解算法临时准备的稿子,记录自己的点点滴滴。
定义:动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。

递归回顾:给定一个8*8的方格子,如下图所示,求A点到B点的最短路径有多少条?用算法实现。
这里写图片描述
分析:从A到B要求路径最短,则每一步只有两种走法,既向右走和向上走,中途一旦出现向左走和向右走,此时的路径就不是最短路径。于是就可以用坐标x和y分别记录出向右走和向上走情况。用函数F(m,n,x,y)表示路径的数量。
如果x=8或者y=8那么只有一种走法情况 F(m,n,x,y)=1;
如果x<8或者y<8那么F(m,n,x,y)= F(m,n,x+1,y)+ F(m,n,x,y+1);

public int getrsult(int m, int n, int x, int y) {
        if(x==m||y==n)
        {
            return 1;
        }
        if(x<m||y<n)
        {
            return getrsult(m, n, x+1, y)+getrsult(m, n, x, y+1);
        }       
        return 0;
    }

动态规划:背包问题
这里写图片描述
分析:对于7个人物品,每一个物品都可以选择放或者不放进去,因此就有两种结果。取F(I,weightleft)表示最大值,其中I为当前物品标号,weightleft为当前背包剩下的容量,CurrentObject表示当前物品
1, 当CurrentObjectWeight>M,放不进去,F(I,weightleft)= F(I+1,weightleft)
2,当CurrentObjectWeight《M,能放进去,但可以选择放或者不放。
F(I,weightleft)=max(F(I+1,weightleft)+F(I,weightleft-currentObjectWeight)+currentObjectValue;);

这里写代码片

介绍动态规划之前一定要现讲递归,动态规划其实就是在递归之上延生出来的,递归的算法本质上是数形结构的深度优先遍历,按照深度优先的原则,仅仅一个return语句就能把所有的路线全部走一遍。每走到头加1,因此得到结果。动态规划就是在深度遍历的时候加一个限制条件,比如上面背包问题,本质为递归,但是在深度遍历到头的时候,加一个比较相邻两个深度遍历得到的值,谁大,记录下谁。然后和相邻的树形节点比较,再取大值,一直取到最上层的树形节点,拿到背包的最优解。
上图的最短路径问题,如果每条路径上面加一个需要消耗的体力v,然后怎么走既是最短,又消耗体力最小,求消耗体力最小值,这样也就是在每次遍历的时候加一个比较条件就行了,然后记录下最小值,也就变成动态规划了。

背包代码:

public class DP {
    private BEAN bean[] = { new BEAN(35, 10), new BEAN(30, 40),
            new BEAN(6, 30), new BEAN(50, 50), new BEAN(40, 35),
            new BEAN(10, 40), new BEAN(25, 30) };

    private int maxWeight;
    private int record[][];

    public DP(int maxWeight) {
        this.maxWeight = maxWeight;
        int m = bean.length + 1;
        int n = maxWeight + 1;
        record = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                record[i][j] = -1;
            }
        }
    }

    public int getResult(int i, int maxWeight) {
        int result;
        if (record[i][maxWeight] != -1) {
            result = record[i][maxWeight];
        }
        if (i >= bean.length) {
            return 0;
        }
        if (bean[i].getWeight() > maxWeight) {
            result = getResult(i + 1, maxWeight);
        } else {
            result = Math.max(
                    getResult(i + 1, maxWeight),
                    getResult(i + 1, maxWeight - bean[i].getWeight())
                            + bean[i].getValue());
        }

        record[i][maxWeight] = result;
        return result;
    }

    public static void main(String[] s) {
        DP test = new DP(150);
        int result = test.getResult(0, 150);
        System.out.println(result);
    }

}
public class BEAN {
    private int weight;
    private int value;

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public BEAN(int weight, int value) {
        this.weight = weight;
        this.value = value;
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值