数据结构与算法Day34----动态规划(二)

一、理论:

1、一个模型三个特征:

<1>、“一个模型”:

  它指的是动态规划适合解决的问题的模型。一般是用动态规划来解决最优问题。而解决问题的过程,需要经历多个决策阶段。每个决策阶段都对应着一组状态。然后寻找一组决策序列,经过这组决策序列,能够产生最终期望求解的最优值。

<2>、“三个特征”:

  1. 最优子结构
      最优子结构指的是,问题的最优解包含子问题的最优解。反过来说就是,可以通过子问题的最优解,推导出问题的最优解。如果把最优子结构对应到动态规划问题模型上,那也可以理解为,后面阶段的状态可以通过前面阶段的状态推导出来。
  2. 无后效性
      无后效性有两层含义,第一层含义是,在推导后面阶段的状态的时候,只关心前面阶段的状态值,不关心这个状态是怎么一步一步推导出来的。第二层含义是,某阶段状态一旦确定,就不受之后阶段的决策影响。无后效性是一个非常“宽松”的要求。只要满足前面提到的动态规划问题模型,其实基本上都会满足无后效性。
  3. 重复子问题
      不同的决策序列,到达某个相同的阶段时,可能会产生重复的状态。

<3>、“一个模型三个特征”实例剖析:

  假设有一个n乘以n的矩阵w[n][n]。矩阵存储的都是正整数。棋子起始位置在左上角,终止位置在右下角。将棋子从左上角移动到右下角。每次只能向右或者向下移动一位。从左上角到右下角,会有很多不同的路径可以走。把每条路径经过的数字加起来看作路径的长度。那从左上角移动到右下角的最短路径长度是多少呢?

(1)、是否符合“一个模型”?

  从(0, 0)走到(n-1, n-1),总共要走2*(n-1)步,也就对应着2*(n-1)个阶段。每个阶段都有向右走或者向下走两种决策,并且每个阶段都会对应一个状态集合。把状态定义为min\_dist(i, j),其中i表示行, j表示列。min\_dist表达式的值表示从(0, 0)到达(i, j)的最短路径长度。所以,这个问题是一个多阶段决策最优解问题,符合动态规划的模型。

(2)、是否符合“三个特征”?

  刚刚定义状态的时候,把从起始位置(0, 0)(i, j)的最小路径,记作min\_dist(i, j)。因为只能往右或往下移动,所以,只有可能从(i, j-1)或者(i-1, j)两个位置到达(i, j)。也就是说,到达(i, j)的最短路径要么经过(i, j-1),要么经过(i-1, j),而且到达(i, j)的最短路径肯定包含到达这两个位置的最短路径之一。换句话说就是, min\_dist(i, j)可以通过min\_dist(i, j-1)min\_dist(i-1, j)两个状态推导出来(min\_dist(i, j) = w[i][j] + min(min\_dist(i, j-1), min\_dist(i-1, j)))。这就说明,这个问题符合“最优子结构”。

  如果走到(i, j)这个位置,只能通过(i-1, j)(i, j-1)这两个位置移动过来,也就是说,想要计算(i, j)位置对应的状态,只需要关心(i-1, j)(i, j-1)两个位置对应的状态,并不关心棋子是通过什么样的路线到达这两个位置的。而且,仅仅允许往下和往右移动,不允许后退,所以,前面阶段的状态确定之后,不会被后面阶段的决策所改变,所以,这个问题符合“无后效性”这一特征。

  可以用回溯算法来解决这个问题。从左上角到节点对应的位置,有多种路线,说明这个问题中存在“重复子问题”。

二、动态规划解题思路总结:

1、状态转移表法:

  首先画出递归树,然后根据递归树画出一个状态表。状态表一般都是二维的,所以可以把它想象成二维数组。其中,每个状态包含三个变量,行、列、数组值。根据决策的先后过程,从前往后,根据递推关系,分阶段填充状态表中的每个状态。最后,将这个递推填表的过程,翻译成代码,就是动态规划代码了。



public int minDistDP(int[][] matrix, int n) {
    int[][] states = new int[n][n];
    int sum = 0;
    for (int j = 0; j < n; ++j) { // 初始化states的第一行数据
        sum += matrix[0][j];
        states[0][j] = sum;
    }
    sum = 0;
    for (int i = 0; i < n; ++i) { // 初始化states的第一列数据
        sum += matrix[i][0];
        states[i][0] = sum;
    }
    for (int i = 1; i < n; ++i) {
        for (int j = 1; j < n; ++j) {
            states[i][j] =matrix[i][j] + Math.min(states[i][j-1], states[i-1][j]);
        }
    }
    return states[n-1][n-1];
}

2、状态转移方程法:

  分析某个问题如何通过子问题来递归求解,也就是所谓的最优子结构。根据最优子结构,写出递归公式,也就是所谓的状态转移方程。有了状态转移方程,代码实现就非常简单了。一般情况下,有两种代码实现方法,一种是递归加“备忘录”,另一种是迭代递推。
状态转移方程:min\_dist(i, j) = w[i][j] + min(min\_dist(i, j-1), min\_dist(i-1, j))

递归加“备忘录”代码:
private int[][] matrix ={{1, 3, 5, 9},
                         {2, 1, 3, 4}, 
                         {5, 2, 6, 7}, 
                         {6, 8, 4, 3}};
private int n = 4;
private int[][] mem = new int[4][4];
public int minDist(int i, int j) { // 调用minDist(n-1, n-1);
    if (i == 0 && j == 0) return matrix[0][0];
    if (mem[i][j] > 0) return mem[i][j];
    int minLeft = Integer.MAX_VALUE;
    if (j-1 >= 0) {
        minLeft = minDist(i, j-1);
    }
    int minUp = Integer.MAX_VALUE;
    if (i-1 >= 0) {
        minUp = minDist(i-1, j);
    }
    int currMinDist = matrix[i][j] + Math.min(minLeft, minUp);
    mem[i][j] = currMinDist;
    return currMinDist;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容