无法从CodeChef解决练习[简单]

时间:2012-05-22 01:21:10

标签: algorithm graph-algorithm

所以,基本上我感觉非常愚蠢,因为this exercise,我花了4到5个小时尝试编码,到目前为止我还没有成功。

我已经意识到使用Longest Path方法通过树遍历可以更容易地解决这个问题,但我不确定(你能否向我确认一下。),可能会过度杀死,因为它应该是一个容易出问题的问题,所以,请你帮助我提供一些指导或基本步骤或算法方法来解决这个问题?各种帮助当然值得赞赏。

PS。我通常会发布一些关于我到目前为止所做的事情的代码,但我相信到目前为止,一切都是错误的,我宁愿从头开始,至少在想法方面。

感谢。

根据请求,这里是根据解决练习的接受答案输入的代码:

def get_max_sum(matrix)
  (1...matrix.length).each do |index|  
    flag = 0  
    matrix[index].each_with_index do |e, i|    
      add = (matrix[index-1][flag] > matrix[index-1][flag+1]) ? matrix[index-1][flag] : matrix[index-1][flag+1]
      e += add
      matrix[index][i] = e
      flag = flag + 1
    end    
  end
  matrix[-1][0]
end

矩阵参数是一个数组数组,每个数组代表三角形中的一行。

3 个答案:

答案 0 :(得分:6)

如果从底部开始并逐步提升,这个问题很容易。考虑三角形

   1
  1 2
 4 1 2
2 3 1 1

查看倒数第二行。如果通过三角形的某个路径到达4,你将向右移动到3,得到7的总和(加上它上面的路径中的任何东西)。如果你已经达到1,你将向左移动到3,得到4的总和(加上它上面的路径中的任何东西)。如果你在2,你可以移动任何一种方式获得3的总和(加上它上面的路径中的任何东西)。因此,通过用总和替换倒数第二行,三角形

  1
 1 2
7 4 3

将具有与原始三角形相同的最大和路径。现在以递减三角形递归地执行相同的过程。从倒数第二行的1开始向左移动到7,得到8的总和,从2向左移动到4,得到6的总和。现在看起来像减少的三角形

 1
8 6

最后,从倒数第二行的1开始向左移动到8,总和为9,这就是问题的答案。

还有一种自上而下的工作方法。在每一步中,将三角形中的每个数字替换为通向该数字的任何路径的最大总和。从顶部开始,三角形开始

1

然后第二行被其总和替换

 1
2 3

然后是第三行

  1
 2 3
6 4 5

最后是第四行

   1
  2 3
 6 4 5
8 9 6 6

答案是底行中最大的总和,即9。我总是发现自上而下的方法比自下而上的方法更难管理,但这两种算法是相互对立的,所以它是你选择哪个实施。自上而下的方法确实具有以下优势:您可以在读取数据时累积下一行;使用自下而上的方法,您必须在计算任何总和之前读取并存储整个输入。

我会留给你写代码。执行此操作时,请记住,您一次只需要存储两行,即前一行和下一行。哪个是上一个,哪个是下一个取决于您是自上而下还是自下而上 - 前一行是您刚刚填写的行,下一行是您当前正在处理的行,这意味着如果你自上而下工作,下一行的总和比上一行多一个,如果你自下而上工作,下一行的总和比前一行少一个。请在工作时发布您的代码,以便其他人可以从您的努力中学习。

顺便说一下,这个问题最初来自Project Euler。 Code Chef偷了它们,显然没有归属,这真的不是一件好事。

答案 1 :(得分:1)

注意:原始帖子中的问题陈述假设一个严格的直角三角形:

on each path the next number is located on the row below,
more precisely either directly below or below and one place to the right.

另请查看他们提供的示例以确认这一点。

解答:

  • 1]使用二维数组存储三角形

  • 根据规则重新计算三角形

  • 走三角形的最后一行 - 即基数 - 以找到最大值。

CODE:

import java.util.Arrays;

public class NumberTriangle {

    //MAIN IS FOR TESTING ONLY
public static void main(String[] ars) {
    int[][] input = { { 1 }, { 4, 8 }, { 9, 8, 7 }, { 1, 3, 6, 9 },
            { 7, 5, 2, 7, 3 } };

    int max = compute(input);// answer: max length
    // not necessary; but shows new triangle
    for (int[] A : input)
        System.out.println(Arrays.toString(A));

    // print the answer
    System.out.println("Largest number: " + max);
}

    //THIS IS THE SOLUTION
public static int compute(int[][] input) {
    //compute new triangle
    for (int y = 1; y < input.length; y++)
        for (int x = 0; x < input[y].length; x++) {
            int first = x - 1 > 0 ? x - 1 : 0;
            int last = x < input[y - 1].length ? x
                    : input[y - 1].length - 1;
            int max = Math.max(input[y - 1][last], input[y - 1][first]);
            input[y][x] += max;
        }
    //extract max value;
    int max = -1;
    int lastRow = input[input.length - 1].length;
    for (int x = 0, y = input.length - 1; x < lastRow; x++)
        if (max < input[y][x])
            max = input[y][x];
    return max;
}// compute
}

测试用例的答案:

[1]
[5, 9]
[14, 17, 16]
[15, 20, 23, 25]
[22, 25, 25, 32, 28]

Largest number: 32

答案 2 :(得分:0)

最长路径寻找方法对我来说感觉不对,因为每条路径都是N-1边长。我想我会假装输入是一个二叉树并找到树中最大的元素 - 找到底部两行的最大总和,在倒数第二行记忆结果,然后向上移动另一行行。 (我希望这有点意义......)