Euler project #18 approach

后端 未结 9 864
鱼传尺愫
鱼传尺愫 2020-11-30 22:23

I am looking into an Euler project. Specifically #18.
To sum up, the idea is to find the max path from a triangle:

   3
  7 4
 2 4 6  
8 5 9 3
<         


        
相关标签:
9条回答
  • 2020-11-30 22:49

    It's something called dynamic programming.

    You have such triangle:

       3
      7 4
     2 4 6  
    8 5 9 3
    

    When you move from the bottom to the top, you can calculate the best choices on last iteration. In this case you take the last row 8 5 9 3 and maximize sum in addition to previous line.

    Iteration 1: Assume that you are on last-1 step.

    You have line 2 4 6, let's iterate on it.

    From 2, you can go to either 8 or 5, so 8 is better (maximize your result from 2) so you calculate first sum 8 + 2 = 10.

    From 4, you can go to either 5 or 9, so 9 is better (maximize your result from 4) so you calculate second sum 9 + 4 = 13.

    From 6, you can go to either 9 or 3, so 9 is better again (maximize your result from 6) so you calculate third sum 9 + 6 = 15.

    This is the end of first iteration and you got the line of sums 10 13 15.

    Now you've got triangle of lower dimension:

        3
      7  4
    10 13 15  
    

    Now go on until you get one value, which is exactly 23.

    0 讨论(0)
  • 2020-11-30 22:52

    Taking a bottom up approach eliminates paths while going top-down only adds potential paths.

    Because you're eliminating bad paths quicker, doing a breadth-first search becomes the optimal solution. A depth-first search in either direction is both wrong (as you've shown) and slow.

    0 讨论(0)
  • 2020-11-30 22:58
    static int getTriangle() throws FileNotFoundException, IOException{
            File file = new File("/home/rakib/This Pc/programming/problem solving/ProjectEuler/src/projecteuler/euluer17.txt");
            BufferedReader br = new BufferedReader(new FileReader(file));
            String n;
            int i = 0;
            int [][] array = new int[15][15];
            while((n = br.readLine()) != null){
                String [] temp = n.split(" ");
                for(int j = 0; j < temp.length; j++){
                     array[i][j] = Integer.parseInt(temp[j]);         
                }
                 i++;
            }
    
    
        for(int j = array.length-2; j >= 0; j--){
            int []tempArray = new int [j+1];
               for(int k =0; k <= j; k++){
                   tempArray[k] = array[j][k] + Math.max(array[j+1][k], array[j+1][k+1]);
               }
               array[j] = tempArray;
        }
    
     return array[0][0];
    }
    

    i used bottom up approach to solve this problem. working from last two row. just add max value with path element.

    0 讨论(0)
  • 2020-11-30 22:59

    The difference is not between top-down and bottom-up. The difference is between greedy and 'frontier' methods.

    A greedy algorithm won't necessarily help you, because you can't recover if the best part of the tree gets out of reach. For example: a greedy algorithm would choose the path 1-3 from top to bottom. It would miss the 9 entirely.

        1
       2 3
      9 1 1
    

    In order to find the true maximum, you'd have to essentially traverse nearly all paths.

    The bottom-up approach, as it is described, doesn't have this problem. It examines at most n*(n-1) paths: 2 for each element. However, calling it the 'bottom-up' approach is misleading.

    Why? Because there is a top-down approach that is equivalent. The essence is that you have a kind of 'frontier' with best results for all trees behind the frontier. Whether you move the frontier up or down is secondary. For the top-down approach in the above example, you calculate for each row the sum of each element and the maximum of the two best totals above it:

         1
        3 4
      12 5 5
    

    In the bottom-up approach, you calculate for each row the sum of each element and the maximum of the two best totals below it. In reverse order:

      9  1 1
       11 4
        12
    

    There is about equal work in both these top-down and bottom-up approaches.

    0 讨论(0)
  • 2020-11-30 23:01

    Actually, you needn't start bottom-up; you may as well start top-down, providing you do it properly.

    The way it works bottom up is best illustrated by the taking what happes at each level of the pyramid. The path surely must cross each level at some point.

        x
       x x
      x h x
     x y y x
    x y y y x
    

    Let's say it's h. From the definition of allowable paths, the path can only follow down into the y-marked places, which forms a problem similar to the original - if we find a maximal path through the ys and the maximal path of the whole triangle actually goes through h, it will surely follow along a maximal path in ys (if not, you can switch the part of path in the smaller triangle and get an overall better path).

    So if you structure your algorithm top-down computing the maximal path from the current node down, you get the correct result (ie. maximal path value, from which you can easily get the path itself).

    Now, this takes O(N) (N meaning the number of the numbers), because for each place, you just consider two paths and use the pre-computed values from the lower level.

    Virtually the same algorithm can be implemented top down, where you start at the top and recurse down, provided you memoize the result.

    best_length(node)
    { 
      if(node is terminal)
        return value(node)
      int m = 0
      for(next : lower neighbors of node)
        m = max(best_length(next), m)
      return m + value(node);
    }
    

    Another possibility of doing this top-down would be just reverse the computation. You start at the top, for each node considering its upper neighbors, and get the path length from the top ending in this node (instead of the path going from this node down to the bottom row). At the end, you gather the data from the bottom row and you're done.

    0 讨论(0)
  • 2020-11-30 23:01

    Here is a complete answer:

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
      int sum1,sum2;
      int A[4][4] = {{3,0,0,0},{7,4,0,0},{3,4,6,0},{8,5,9,3}};
      for(int i=2;i>=0;i--){
         for(int j=0;j<4;j++){
            sum1=A[i][j]+A[i+1][j];
            sum2=A[i][j]+A[i+1][j+1];
            if(sum1>sum2){
                A[i][j]=sum1;
            }
            else{
                A[i][j]=sum2;
            }
         }
      }
      cout<<A[0][0]<<endl;
    }
    
    0 讨论(0)
提交回复
热议问题