Friday, 31 May 2013

Find The Maximum Sum in Triangle From Top to Bottom (Euler Problem).

By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.
3
7 4
2
4 6
8 5
9 3
That is, 3 + 7 + 4 + 9 = 23.

Brute Force

When answering the problem with a brute force solution, it is pretty simple to go through the steps, we just need to try all combinations. Since we have a binary choice each time. We can iterate through all possibilities with a normal integer counter, and use the bits of the number to pick the direction left or right. While running through the path, we sum up the numbers and check if they are larger than the current maximum found.It is not possible to try every route to solve this problem (where the base of the triangle has 100 numbers), as there are 2^(99) altogether! If you could check one trillion (10^(12)) routes every second it would take over twenty billion years to check them all.

Dynamic Programming

 Two Sub-problems
Standing at the top of the triangle we have to choose between going left and right. In order to make the optimal choice (which maximizes the sum), we would have to know how large a sum we can get if we go either way. We have to solve the two smaller problems which I have marked with blue and the orange in the figure to the right.
Solving a sub-problem

We can break each of the sub-problems down in a similar way, and we can continue to do so until we reach a sub-problem at the bottom line consisting of only one number, then the answer is the number it self. Once that question is answered we can move up one line, and answer the questions posed there with a solution which is a + max(b,c).
Once we know the answer to all 3 sub-problems on the next to last line, we can move up and answer the posed sub-problems by the same formula already applied. And we can continue to do so until we reach the original question of whether to go left or right

Savings with Dynamic Programming

If we want to solve the small problem with brute force, we would need to test all 8 paths, each resulting in 3 additions, in total 24 additions.
If we use dynamic programming, the first iteration would require 3 maximum comparison operations and 3 additions. The next line would require 2 maximum comparison operations and 2 additions, and the first line would require one of each. So a total of 6 maximum comparison operations and 6 additions.

Dynamic Programming – The Algorithm

We can make a short-cut with the algorithm, as we don’t have to break the problem into sub-problems, but can start from the bottom and work the way up through the triangle until we reach the top and the algorithm spits out a number.
We start with a triangle that looks like
3
7 4
2 4 6
8 5 9 3
Applying the algorithm to the small problem we will need three iterations. The first iteration we apply the rule a + max(b,c) which creates a new triangle which looks as
3
7 4
10 13 15
Making the second iteration of the algorithm makes the triangle look
3
20 19
And if we run the algorithm once more, the triangle collapses to one number – 23 – which is the answer to the question.

Program:

#include<stdio.h>
int main(void)
{
    int j,t,n,i,a[100][100];
    printf("hi\n");
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            for(j=0;j<=i;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        for(i=n-2;i>=0;i--)
        {
            for(j=0;j<=i;j++)
            {
                a[i][j]+=a[i+1][j]>a[i+1][j+1]?a[i+1][j]:a[i+1][j+1];
            }
        }
        printf("%d\n",a[0][0]);
    }
    return 0;
}
Time complexity:O(n^2) where n is the number of rows.
we traverse through  n-1  elements on (n-2)th line, (n-2) elements on (n-3)th line and so on till 1 element in first line, a total of 1+2+..+(n-1) elements i.e. (n-1)n/2 or O(n^2) eelments.
At each element, an adition and comparision operation is performed in O(1) time.

3 comments:

  1. const maxSum = (pyramid) {
    return pyramid.reduceRight((last, current) => current.map(
    (value, index) => value + Math.max(last[index], last[index+1])
    ))[0]
    }

    ReplyDelete
  2. java code


    public class NewOne {

    public static void main(String[] args) {
    // TODO Auto-generated method stub
    int[][] max= {{3},{1,4},{2,4,6},{8,5,9,3}};
    for(int i=max.length-2;i>=0;--i) {
    for(int j=0;j=max[i+1][j+1]+max[i][j]) {
    max[i][j]=max[i+1][j]+max[i][j];
    }
    else {
    max[i][j]=max[i+1][j+1]+max[i][j];
    }
    }
    }
    System.out.println(max[0][0]);
    }

    }

    ReplyDelete
  3. your implementation is not top to bottom, it is a bottom up approach.

    ReplyDelete