博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
动态规划之最小带权路径(Min Cost Path)
阅读量:4097 次
发布时间:2019-05-25

本文共 3500 字,大约阅读时间需要 11 分钟。

原文地址:

已知一个成本矩阵cost[][],位置(m, n)的权重是cost[][],写一个函数,这个函数返回从(0, 0)到(m, n)的最小带权路径。矩阵的每个格子表示的是通过这个格子的代价。到达(m, n)的路径总代价是这条路上所有代价和(包括出发点和终点)。你只可以从当前的格子向下,向右,或者对角线移动到下面的格子。例如给定(i, j),只可以移动到cells (i+1, j),(i, j+1) 和(i+1, j+1)。你可以假设所有的成本都是正整数。

例如,在下面的图中,到(2, 2)的最小带权路径是啥?

这里写图片描述

最小带权路径在下面的图中已经标记出来了,路径是(0, 0) –> (0, 1) –> (1, 2) –> (2, 2)。路径的成本是8 (1 + 2 + 2 + 3)。

这里写图片描述

1)最优的子结构

到达 (m, n) 的路径必须通过下面三个格子中的一个:(m-1, n-1)或者(m-1, n)或者(m, n-1)。所以到达(m, n)的最小成本快一些写成“到达三个格子的最小值加上cost[m][n]”。

minCost(m, n) = min (minCost(m-1, n-1), minCost(m-1, n), minCost(m, n-1)) + cost[m][n]

2)重复的子问题

下面是MCP(Minimum Cost Path)问题的一个比较简单的递归实现了。这个实现就是根据上面的递归结构来写的。

/* A Naive recursive implementation of MCP(Minimum Cost Path) problem */#include
#include
#define R 3#define C 3int min(int x, int y, int z);/* Returns cost of minimum cost path from (0,0) to (m, n) in mat[R][C]*/int minCost(int cost[R][C], int m, int n){ if (n < 0 || m < 0) return INT_MAX; else if (m == 0 && n == 0) return cost[m][n]; else return cost[m][n] + min( minCost(cost, m-1, n-1), minCost(cost, m-1, n), minCost(cost, m, n-1) );}/* A utility function that returns minimum of 3 integers */int min(int x, int y, int z){ if (x < y) return (x < z)? x : z; else return (y < z)? y : z;}/* Driver program to test above functions */int main(){ int cost[R][C] = { {
1, 2, 3}, {
4, 8, 2}, {
1, 5, 3} }; printf(" %d ", minCost(cost, 2, 2)); return 0;}

应该注意的是,上面的方法重复计算了一些子问题,看下面这个递归树,有许多节点出现了多次,这个递归的时间复杂度是指数级的,运行起来超慢。

mC refers to minCost()                                    mC(2, 2)                          /            |           \                         /             |            \                              mC(1, 1)           mC(1, 2)             mC(2, 1)              /     |     \       /     |     \           /     |     \              /      |      \     /      |      \         /      |       \       mC(0,0) mC(0,1) mC(1,0) mC(0,1) mC(0,2) mC(1,1) mC(1,0) mC(1,1) mC(2,0)

所以MCP问题有动态规划的两个属性(重复子问题与最优子结构),就像其他典型的DP问题一样,可以通过自底向上地构建一个临时数组tc[][]来避免重复计算相同的子问题。

/* Dynamic Programming implementation of MCP problem */#include
#include
#define R 3#define C 3int min(int x, int y, int z);int minCost(int cost[R][C], int m, int n){ int i, j; // Instead of following line, we can use int tc[m+1][n+1] or // dynamically allocate memoery to save space. The following line is // used to keep te program simple and make it working on all compilers. int tc[R][C]; tc[0][0] = cost[0][0]; /* Initialize first column of total cost(tc) array */ for (i = 1; i <= m; i++) tc[i][0] = tc[i-1][0] + cost[i][0]; /* Initialize first row of tc array */ for (j = 1; j <= n; j++) tc[0][j] = tc[0][j-1] + cost[0][j]; /* Construct rest of the tc array */ for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) tc[i][j] = min(tc[i-1][j-1], tc[i-1][j], tc[i][j-1]) + cost[i][j]; return tc[m][n];}/* A utility function that returns minimum of 3 integers */int min(int x, int y, int z){ if (x < y) return (x < z)? x : z; else return (y < z)? y : z;}/* Driver program to test above functions */int main(){ int cost[R][C] = { {
1, 2, 3}, {
4, 8, 2}, {
1, 5, 3} }; printf(" %d ", minCost(cost, 2, 2)); return 0;}

输出:

8

这个实现的时间复杂度是 O(mn),这比前面那个简单的递归实现好多了。

你可能感兴趣的文章
windows下添加环境变量
查看>>
windows下安装python包pip时出错DEPRECATION解决
查看>>
pip install 各种包时出现报asciii码错误的问题
查看>>
实现一个简单的python小脚本的一些必要步骤
查看>>
python2.7中print(end=' ')不能用?
查看>>
php+nginx环境配置
查看>>
nginx:403 forbidden 的解决办法
查看>>
安装php7+nginx所遇到的一些问题及解决办法
查看>>
php启动出现Cannot bind/listen socket等问题
查看>>
php7+nginx下安装mysql5.7出现的一些问题及解决/以及一些mysql常用方法
查看>>
多益网络前端面试反思题
查看>>
高效的利用pandas读取多个sheet的excel文件
查看>>
excel宏设置之一键生成多张sheet并写入内容与格式
查看>>
Django model中的 class Meta 详解
查看>>
mysql历史拉链表
查看>>
python查询数据库后生成excel
查看>>
大文件分组上传以及进度条
查看>>
python字符串与时间互相转换
查看>>
HttpResponse和HttpResquest与会话技术
查看>>
前端页面上传文件夹的方法
查看>>