原文地址 http://www.daileinote.com/computer/math/0f
最小开销路径(Min Cost Path)(MCP),给出一个开销矩阵cost,求得从cost[x][y] 到 cost[i][j] 的最小开销。比如下图
从 (0,0) 到 (2,2) 的最小开销为 8 (1 + 2 + 2 + 3)
想要到达 (m, n),必须经过 (m-1, n-1),(m-1, n),(m, n-1) 其中一个, 所以 minCost(m, n) = min (minCost(m-1, n-1), minCost(m-1, n), minCost(m, n-1)) + cost[m][n]
下面是没有解决重叠子问题的例子
#include <stdio.h>
#include <string.h>
#define dl_max(x,y) ((x) > (y) ? (x) : (y))
#define MAX_COST 1024 // 这里定义一个上限
int dl_min(int x, int y, int z) { if (x < y) return x < z ? x : z; else return y < z ? y : z;}
int min_cost(int cost[3][3], int m, int n)
{
if (m < 0 || n < 0)
return MAX_COST;
if (m == 0 && n == 0)
return cost[m][n];
return cost[m][n] + dl_min(min_cost(cost, m-1,n), min_cost(cost, m,n-1), min_cost(cost, m-1,n-1));
}
int main()
{
int cost[3][3] = {
{1, 2, 3},
{4, 8, 2},
{1, 5, 3}
};
printf("min cost: %d\n", min_cost(cost, 2, 2));
}
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)
上面有很多重复计算的问题,跟其他动态规划问题一样,这里满足 最优子结构 和 重叠子问题,可以构建 arr[][]解决
#include <stdio.h>
#include <string.h>
int dl_min(int x, int y, int z) { if (x < y) return x < z ? x : z; else return y < z ? y : z;}
int min_cost(int cost[3][3], int m, int n)
{
int i,j,sum[3][3];
sum[0][0] = cost[0][0];
//计算第一列
for (i = 1; i <= m; i++)
sum[i][0] = sum[i-1][0] + cost[i][0];
//计算第一行
for (i = 1; i <=n; i++)
sum[0][i] = sum[0][i-1] + cost[0][i];
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++) {
sum[i][j] = cost[i][j] + dl_min(sum[i-1][j], sum[i][j-1], sum[i-1][j-1]);
}
}
return sum[m][n];
}
int main()
{
int cost[3][3] = {
{1, 2, 3},
{4, 8, 2},
{1, 5, 3}
};
printf("min cost: %d\n", min_cost(cost, 2, 2));
}
时间复杂度为 O(mn)
原文地址 http://www.daileinote.com/computer/math/0f