n x n整数矩阵的动态规划算法求最大和

时间:2016-10-11 21:25:52

标签: java algorithm dynamic-programming

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

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|

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

1 个答案:

答案 0 :(得分: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。此代码有助于用于调整整数值(来自strings / println)并导致以下两种方法。注意:debug / 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 result = maxVertical + maxHorizo​​ntal + maxDiagonal + maxAntiDiagonal; System.out.println(“Result =”+ result);

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

  3.   

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

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