【问题标题】:Does this problem have overlapping subproblems?这个问题有重叠的子问题吗?
【发布时间】:2021-10-26 02:33:44
【问题描述】:

我正在尝试解决 LeetCode.com 上的this question

给你一个 m x n 整数矩阵 mat 和一个整数目标。从矩阵的每一行中选择一个整数,以使目标与所选元素之和之间的绝对差异最小化。返回最小绝对差。 (两个数 a 和 b 的绝对差就是 a - b 的绝对值。)
所以对于输入mat = [[1,2,3],[4,5,6],[7,8,9]]target = 13,输出应该是0(因为1+5+7=13)。

referring的解决方案如下:

int dp[71][70 * 70 + 1] = {[0 ... 70][0 ... 70 * 70] = INT_MAX};
int dfs(vector<set<int>>& m, int i, int sum, int target) {
    if (i >= m.size())
        return abs(sum - target);
    if (dp[i][sum] == INT_MAX) {
        for (auto it = begin(m[i]); it != end(m[i]); ++it) {
            dp[i][sum] = min(dp[i][sum], dfs(m, i + 1, sum + *it, target));
            if (dp[i][sum] == 0 || sum + *it > target)
                break;
        }
    } else {
        // cout<<"Encountered a previous value!\n";
    }

    return dp[i][sum];
}
int minimizeTheDifference(vector<vector<int>>& mat, int target) {
    vector<set<int>> m;
    for (auto &row : mat)
        m.push_back(set<int>(begin(row), end(row)));
    return dfs(m, 0, 0, target);
}

我不明白这个问题是如何通过动态编程来解决的。这些状态显然是i 行和sum 行(从0 行到i-1 行)。鉴于问题约束是:

m == mat.length
n == mat[i].length
1 <= m, n <= 70
1 <= mat[i][j] <= 70
1 <= target <= 800

我的理解是,我们永远不会遇到以前遇到过的sum(所有值都是正数)。即使是我添加的调试cout 语句也不会在问题中给出的示例输入上打印任何内容。

动态规划如何应用在这里?

【问题讨论】:

    标签: c++ algorithm dynamic-programming


    【解决方案1】:

    这个问题是 NP-hard,因为 0-1 背包问题很容易归结为它。

    这个问题还有一个动态规划解,类似于0-1背包的解:

    1. 找出您可以用第一行中的数字(即第一行中的数字)得出的所有总和:
    2. 对于随后的每一行,将第 i 行中的所有数字添加到所有先前可访问的总和中,以找到在 i 行之后可以得到的总和。

    如果您需要能够重新创建通过矩阵的路径,那么对于每个级别的每个总和,请记住上一级别的前一个。

    确实存在重叠的子问题,因为通常有多种方法可以得到很多总和,而您只需要记住并从其中一种继续。

    这是你的例子:

    sums from    row 1:  1, 2, 3
    sums from rows 1-2:  5, 6, 7, 8, 9
    sums from rows 1-3:  12, 13, 14, 15, 16, 17, 18
    

    如您所见,我们可以得出目标总和。有几种方法:

    7+4+2, 7+5+1, 8+4+1
    

    像 15 这样的一些目标有更多方法。随着矩阵大小的增加,重叠量趋于增加,因此这种解决方案在许多情况下都相当有效。总复杂度为 O(M * N * max_weight)。

    但是,这个一个 NP-hard 问题,所以这并不总是容易处理的——max_weight 会随着问题的大小呈指数增长。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-16
      • 2020-10-17
      • 2020-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-05
      • 2015-11-28
      相关资源
      最近更新 更多