最小路径开销

最小开销路径(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)


参考:

geeksforgeeks


上一篇: 最长公共子序列
下一篇: 硬币改变
作者邮箱: 203328517@qq.com