【问题标题】:Dynamic programming algorithm for n x n matrix of integers to find maximum sumn x n 整数矩阵的动态规划算法以找到最大和
【发布时间】:2017-02-20 13:43:09
【问题描述】:

我很难理解以下问题,如果有人可以帮助我理解它,我将非常感激。 问题是:

Implement a dynamic programming algorithm for solving the following
problem. The input is an n × n matrix of integers. For the output: 
compute the largest sum of adjacent entries in horizontal, vertical,
diagonal and anti-diagonal direction. Return as output the sum 
h + v + d + c (in suggestive notation) of those four auxiliary results.
The largest (or maximal) sum of an array consisting of only negative  
integers is 0; that is, in that case we select the empty subarray.
A (small) example input matrix with solution 45:
|-2 5 3 2|
|9 -6 5 3|
|1 -8 2 -3|
|-1 2 -5 2|

我的意思是,如果有人可以帮助我朝着正确的方向前进,我将非常感激!!!谢谢

【问题讨论】:

  • 这个问题有什么不清楚的地方?
  • 表示在某个方向上相邻的条目。例如 -6 与 9 垂直相邻,5 和 3 也是如此。(所以该行中的所有条目)
  • @Nia 对于垂直条目的最大总和,我将连续汇总每个条目并寻找其中的最大值。对于水平,它将总结每一列中的条目,然后再次寻找这四个中的最大值
  • @SebastianWalla 非常感谢您帮助我并解释了这一点,我真的很感激!!!!我只有一个小问题,所以我是要对所有 4 个条目求和,还是可以选择例如 2 个相邻的条目,以防 4 个中有 2 个为负数?另外,我看不到上述给定矩阵的总和应该是 45,您能否也快速查看一下,看看 45 是否可能?再次感谢一百万!!!!
  • 在例子中,我相信 h = 9+-6+5+3 = 11, v = 9+1 = 10, d = 5+5 = 10 and c = 9+5 = 14. 或者也许 d 和 c 是相反的,没关系。无论如何,应该是 11 + 10 + 10 + 14 = 45。

标签: java algorithm dynamic-programming


【解决方案1】:

鉴于您的问题陈述:

实现一个动态规划算法来解决以下问题 问题。输入是一个 n × n 整数矩阵。对于输出: 计算水平,垂直,相邻条目的最大总和, 对角线和反对角线方向。返回总和作为输出 h + v + d + c(暗示性符号)这四个辅助结果。 仅由负数组成的数组的最大(或最大)和
整数为 0;也就是说,在这种情况下,我们选择空子数组。 具有解 45 的(小)示例输入矩阵:

|-2 5 3 2|
|9 -6 5 3|
|1 -8 2 -3|
|-1 2 -5 2|

然后,阅读您发布的示例输入,我做了一个简短的方法来解析文件中的信息:

public static List<List<Integer>> readFile(final String path) {
    List<List<Integer>> result = new ArrayList<List<Integer>>();
    Path p = Paths.get(path);
    if (!Files.exists(p))
        return null;
    List<String> lines = null;
    try {
        lines = Files.readAllLines(p);
    } catch (IOException e) {
        e.printStackTrace();
    }
    if (lines == null)
        return null;
    for (String str : lines) {
        List<Integer> row = new ArrayList<Integer>();
        final String line = str.substring(1, str.length() - 1);
        String[] arr = line.split(" ");
        for (String s : arr)
            row.add(Integer.valueOf(s.trim()));
        result.add(row);
    }
    return result;
}

垂直方法是直截了当的,循环遍历嵌套数组。

    public static int getVertical(final List<List<Integer>> list) {
        int result = 0;
        for (List<Integer> arr : list) {
            int curr = 0;
            for (Integer val : arr)
                curr += val;
            if (curr > result)
                result = curr;
        }
        return result;
    }

而且水平方向也相当直。注意:为了简单起见,这里我只是使用了一个计数器列表。还有更有效的方法。

    public static int getHorizontal(final List<List<Integer>> list, final int len) {
        List<Integer> sums = new ArrayList<Integer>(list.get(0));
        for (int i = 1; i < len; ++i)
            for (int j = 0; j < len; ++j)
                sums.set(j, sums.get(j) + list.get(i).get(j));
        return Collections.max(sums);
    }

我快速搜索找到一个诊断/反诊断循环question。此代码有助于适应整数值(来自字符串/println's),并导致以下两种方法。注意:调试/system.out.println 用于帮助/显示。

    public static int getDiagonal(final List<List<Integer>> list, final int len) {
        int result = 0;
        // [top half]
        for (int i = len - 1; i > 0; --i) {
            //String temp = "";
            int tmp = 0;
            for (int j = 0, x = i; x <= len - 1; ++j, ++x) {
                final int val = list.get(x).get(j);
                //temp = temp + " " + val;
                tmp += val;
            }
            //System.out.println(temp);
            if (tmp > result)
                result = tmp;
        }
        // [lower half]
        for (int i = 0; i <= len - 1; ++i) {
            //String temp = "";
            int tmp = 0;
            for (int j = 0, y = i; y <= len - 1; ++j, ++y) {
                final int val = list.get(j).get(y);
                //temp = temp + " " + val;
                tmp += val;
            }
            //System.out.println(temp);
            if (tmp > result)
                result = tmp;
        }
        return result;
    }
    public static int getAntiDiagonal(final List<List<Integer>> list, final int len) {
        int result = 0;
        // [top half]
        for (int k = 0; k < len; ++k) {
            int tmp = 0;
            for (int j = 0; j <= k; ++j) {
                int i = k - j;
                int val = list.get(i).get(j);
                //System.out.print(val + " ");
                tmp += val;
            }
            if (tmp > result)
                result = tmp;
            //System.out.println();
        }
        // [lower half]
        for (int k = len - 2; k >= 0; --k) {
            int tmp = 0;
            for (int j = 0; j <= k; ++j) {
                int i = k - j;
                int val = list.get(len - j - 1).get(len - i - 1);
                //System.out.print(val + " ");
                tmp += val;
            }
            if (tmp > result)
                result = tmp;
            //System.out.println();
        }
        return result;
    }

这是解决原始问题的整个程序最终的样子:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class App {
    public static void main(String[] args) {
        List<List<Integer>> data = readFile("C:\\Users\\Nick\\Desktop\\test.txt");
        for (List<Integer> row : data)
            System.out.println(row);
        final int n = data.size();
        int maxVertical = getVertical(data);
        int maxHorizontal = getHorizontal(data, n);
        int maxDiagonal = getDiagonal(data, n);
        int maxAntiDiagonal = getAntiDiagonal(data, n);
        System.out.println("max vertical = " + maxVertical);
        System.out.println("max horizontal = " + maxHorizontal);
        System.out.println("max diagonal = " + maxDiagonal);
        System.out.println("max anti-diagonal = " + maxAntiDiagonal);
    }
    public static int getVertical(final List<List<Integer>> list) {
        int result = 0;
        for (List<Integer> arr : list) {
            int curr = 0;
            for (Integer val : arr)
                curr += val;
            if (curr > result)
                result = curr;
        }
        return result;
    }
    public static int getHorizontal(final List<List<Integer>> list, final int len) {
        List<Integer> sums = new ArrayList<Integer>(list.get(0));
        for (int i = 1; i < len; ++i)
            for (int j = 0; j < len; ++j)
                sums.set(j, sums.get(j) + list.get(i).get(j));
        return Collections.max(sums);
    }
    public static int getDiagonal(final List<List<Integer>> list, final int len) {
        int result = 0;
        // [top half]
        for (int i = len - 1; i > 0; --i) {
            int tmp = 0;
            for (int j = 0, x = i; x <= len - 1; ++j, ++x) {
                final int val = list.get(x).get(j);
                tmp += val;
            }
            if (tmp > result)
                result = tmp;
        }
        // [lower half]
        for (int i = 0; i <= len - 1; ++i) {
            int tmp = 0;
            for (int j = 0, y = i; y <= len - 1; ++j, ++y) {
                final int val = list.get(j).get(y);
                tmp += val;
            }
            if (tmp > result)
                result = tmp;
        }
        return result;
    }
    public static int getAntiDiagonal(final List<List<Integer>> list, final int len) {
        int result = 0;
        // [top half]
        for (int k = 0; k < len; ++k) {
            int tmp = 0;
            for (int j = 0; j <= k; ++j) {
                int i = k - j;
                int val = list.get(i).get(j);
                tmp += val;
            }
            if (tmp > result)
                result = tmp;
        }
        // [lower half]
        for (int k = len - 2; k >= 0; --k) {
            int tmp = 0;
            for (int j = 0; j <= k; ++j) {
                int i = k - j;
                int val = list.get(len - j - 1).get(len - i - 1);
                tmp += val;
            }
            if (tmp > result)
                result = tmp;
        }
        return result;
    }
    public static List<List<Integer>> readFile(final String path) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        Path p = Paths.get(path);
        if (!Files.exists(p))
            return null;
        List<String> lines = null;
        try {
            lines = Files.readAllLines(p);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (lines == null)
            return null;
        for (String str : lines) {
            List<Integer> row = new ArrayList<Integer>();
            final String line = str.substring(1, str.length() - 1);
            String[] arr = line.split(" ");
            for (String s : arr)
                row.add(Integer.valueOf(s.trim()));
            result.add(row);
        }
        return result;
    }
}

最后,鉴于 test.txt 文件包含:

|-2 5 3 2|
|9 -6 5 3|
|1 -8 2 -3|
|-1 2 -5 2|

输出结果(应该是)是:

[-2, 5, 3, 2]
[9, -6, 5, 3]
[1, -8, 2, -3]
[-1, 2, -5, 2]
max vertical = 11
max horizontal = 7
max diagonal = 7
max anti-diagonal = 14

干杯

编辑我意识到我在技术上并没有完全回答原始问题,所以:

  1. 将这两行添加到 main() 方法的最后

    int 结果 = maxVertical + maxHorizo​​ntal + maxDiagonal + maxAntiDiagonal; System.out.println("结果 = " + 结果);

  2. 为每个相应的方法(vert/horiz/diag/anti-diag)添加检查,以便问题中所述的负面事件的情况

仅由负数组成的数组的最大(或最大)和 整数为 0;也就是说,在这种情况下,我们选择空子数组

也可以被覆盖。这不是一个巨大的代码大修论文,更是一个独特的检查。

【讨论】:

  • 嗨尼克,非常感谢您提供如此详细的解释和如此辛勤的工作来解释它。我永远欠你的债。谢谢!!!!!!!!!
  • @OleV.V.感谢您的cmets,我在某种程度上同意您的看法。在理解了这个问题后,我认为自己有不同的方法。对我来说,问题是我不明白问题是什么,这就是我在这里发帖的原因。但是看到不同的方法总是很高兴,这就是为什么我很高兴看到有人花了这么多时间来编写它。你在理解它的基础方面也有很大帮助,我真的需要思考关于我自己的解决方案。非常感谢,别担心这个女孩不是抄写员:)
  • 我将问题陈述解释为包括对任何给定序列中的负数求和,并且只有当整个序列为负时才能将总和更改为零 - 而不是将所有负数否定为零。编辑:assignment?
  • 那我不明白你为什么拿 5,5,(no -3) for 10 diag,而其他 10?为什么总和不是 -3 得到 7?我对您所说的内容或原始发布问题陈述感到困惑 - 您能帮我弄清楚我出错的地方,以便我可以尝试解决我的错误吗?
  • 啊,@NickBell,现在我想我明白其中的区别了。据我了解,您可以采用行、列或对角线的任何子数组。因此,对于对角线 [5, 5, -3],您可能只需要 5 或 [5, 5] 或 [5, 5, -3] 或 [5, -3]。当你取 [5, 5] 时,你得到的总和最大。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 2023-03-06
  • 1970-01-01
相关资源
最近更新 更多