简体   繁体   中英

Path to largest sum

I'm working with the task of finding the path that gives the maximum sum in a triangle.

The one condition I have is having to switch by even and odd numbers for every row.

So in my example I have to go: 55 - 94 - 95 - 72 ... so I change between odd and even numbers. I found this code that uses dynamic programming to find the path with the largest sum. I also know how to check for even or odd number but I don't know how to use it in this algorithm. Can somebody help with this?

public static void Main (string[] args)
    {
        int[,] list = new int[18,19];
        string input = @"55
                        94 48
                       95 30 96
                     77 72 26 67
                    97 13 76 38 45
                  07 36 79 16 37 68
                 48 07 09 18 70 26 06
               18 72 79 46 59 79 29 90
              20 76 87 11 32 07 07 49 18
            27 83 58 35 72 11 25 57 29 85
           14 64 36 96 27 11 58 56 92 18 55
         02 90 03 60 48 49 41 46 33 36 47 23
        92 50 48 02 36 59 42 79 72 20 82 77 42
      56 78 38 80 39 75 02 71 66 66 01 03 55 72
     44 25 67 84 71 67 11 61 40 57 58 89 40 56 36
   85 32 25 85 57 48 84 35 47 62 17 01 01 99 89 52
  06 71 28 75 94 48 37 10 23 51 06 48 53 18 74 98 15
27 02 92 23 08 71 76 84 15 52 92 63 81 10 44 10 69 93";
        var charArray = input.Split ('\n');

        for (int i=0; i < charArray.Length; i++) {
            var numArr = charArray[i].Trim().Split(' ');

            for (int j = 0; j<numArr.Length; j++)
            {
                int number = Convert.ToInt32 (numArr[j]);
                list [i, j] = number;
            }
        }

        for (int i = 16; i >= 0; i--) {
            for (int j = 0; j < 18; j++) {
                list[i,j] = Math.Max(list[i, j] + list[i+1, j], list[i,j] + list[i+1, j+1]);
            }
        }
        Console.WriteLine (string.Format("Maximum total: {0}", list [0, 0]));
    }
}

I have adopted a different approach for your problem.

First I have defined the triangle structure in which - excluding Root and second level, all right hand side children represent also the neighbour left child - excluding the last element on that level.

The traversing of the triangle is pretty simple per se. Once we check for the highest value on that level - we keep track of its parent in order to traverse only trough that path.

using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp8
{
    /// <summary>
    /// The Node class
    /// </summary>
    public class Node
    {
        public int Level { get; set; }
        public List<int> Parents { get; set; }
        public int Element { get; set; }
    }

    /// <summary>
    /// The Triangle class Representation
    /// </summary>
    public class Triangle
    {
        /// <summary>
        /// The triangle root
        /// </summary>
        public int Root { get; set; }

        /// <summary>
        /// The Node per each level of depth
        /// </summary>
        public List<List<Node>> LevelNodes { get; set; }

        /// <summary>
        /// Build the triangle structure
        /// </summary>
        public void BuildTriangle()
        {
            List<Node> nodeLevelList = new List<Node>();
            bool carryOn = true;



            //****************************************************
            //Create Root and second level
            Console.WriteLine("Add Tree Root");
            Root = Convert.ToInt32(Console.ReadLine());
            LevelNodes = new List<List<Node>>();

            //set the first node to have the root has parent
            Node myNode = new Node
            {
                Parents = new List<int> { Root }
            };

            Console.WriteLine("Add Left Child");
            myNode.Element = Convert.ToInt32(Console.ReadLine());
            myNode.Level = 2;
            //add the node
            nodeLevelList.Add(myNode);

            myNode = new Node
            {
                Parents = new List<int> { Root }
            };
            Console.WriteLine("Add Right Child");
            myNode.Element = Convert.ToInt32(Console.ReadLine());
            myNode.Level = 2;
            //add the node
            nodeLevelList.Add(myNode);
            LevelNodes.Add(nodeLevelList);

            //****************************************************

            Console.Clear();

            //****************************************************
            // Build the rest of the triangle data structure
            while (carryOn)
            {
                nodeLevelList = new List<Node>();
                //take all the nodes on last level entered
                var nodes = LevelNodes.Last().ToList();

                bool firstElement = true;


                foreach (var node in nodes)
                {
                    myNode = new Node();

                    if (firstElement)
                    {
                        Console.WriteLine("Add Left Child for parent : {0}", node.Element);
                        myNode.Element = Convert.ToInt32(Console.ReadLine());
                        myNode.Parents = new List<int> { node.Element };
                        myNode.Level = node.Level + 1;
                        //add the node
                        nodeLevelList.Add(myNode);

                        firstElement = false;
                    }
                    else
                    {
                        var temp = nodeLevelList.Last();
                        temp.Parents.Add(node.Element);
                    }

                    //re-initialise node
                    myNode = new Node();
                    Console.WriteLine("Add Right Child for parent : {0}", node.Element);
                    myNode.Element = Convert.ToInt32(Console.ReadLine());
                    myNode.Parents = new List<int> { node.Element };
                    myNode.Level = node.Level + 1;
                    //add the node
                    nodeLevelList.Add(myNode);

                }

                LevelNodes.Add(nodeLevelList);
                Console.Clear();

                Console.WriteLine("Do you wish to continue adding elements ? Y or N");
                carryOn = Console.ReadLine()?.ToLower() == "y";
            }
        }


        public int GetLargetPathSum()
        {
            int result = Root;
            int selectedValue = Root;
            Node nodeSelected = new Node();

            foreach (List<Node> levelNode in LevelNodes)
            {
                int maxValue = 0;

                foreach (Node node in levelNode.Where(x=> x.Parents.Contains(selectedValue)).Select(x=> x).ToList())
                {
                    if (node.Element > maxValue)
                    {
                        maxValue = node.Element;
                        nodeSelected = node;
                    }
                }

                result += maxValue;
                selectedValue = maxValue;
            }

            return result;
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            Triangle triangle = new Triangle();
            triangle.BuildTriangle();

            Console.WriteLine(triangle.GetLargetPathSum());
            Console.ReadLine();

        }
    }
}

Hmmm, quick and dirty. Took your code and simply added it. There are easier ways to do this!

static void Main(string[] args)
        {
            int[,] list = new int[18, 19];
            string input = @"55
                        94 48
                       95 30 96
                     77 72 26 67
                    97 13 76 38 45
                  07 36 79 16 37 68
                 48 07 09 18 70 26 06
               18 72 79 46 59 79 29 90
              20 76 87 11 32 07 07 49 18
            27 83 58 35 72 11 25 57 29 85
           14 64 36 96 27 11 58 56 92 18 55
         02 90 03 60 48 49 41 46 33 36 47 23
        92 50 48 02 36 59 42 79 72 20 82 77 42
      56 78 38 80 39 75 02 71 66 66 01 03 55 72
     44 25 67 84 71 67 11 61 40 57 58 89 40 56 36
   85 32 25 85 57 48 84 35 47 62 17 01 01 99 89 52
  06 71 28 75 94 48 37 10 23 51 06 48 53 18 74 98 15
27 02 92 23 08 71 76 84 15 52 92 63 81 10 44 10 69 93";

            var charArray = input.Split('\n');

            int[] lineArray = new int[18];
            int highestNumber = 0;

            bool even = false;
            bool noHigehestNumberFound = true;

            for (int i = 0; i < 18; i++)
            {
                while (noHigehestNumberFound)
                {
                    //get highest number of a line
                    highestNumber = Convert.ToInt32(charArray[i].Split(' ').Max());
                    if (even != true)
                    {
                        // check odd/even with modulo
                        // if it isn't odd, replace the highest even number with 0
                        if (highestNumber % 2 == 1)
                        {
                            noHigehestNumberFound = false;
                            even = true;
                        }
                        else
                        {
                            StringBuilder builder = new StringBuilder(charArray[i]);
                            builder.Replace(highestNumber.ToString(), "0");
                            charArray[i] = builder.ToString();
                        }
                    }
                    else if (even == true)
                    {
                        // check odd/even with modulo
                        // if it isn't even, replace the highest even number with 0
                        if (highestNumber % 2 == 0)
                        {
                            noHigehestNumberFound = false;
                            even = false;
                        }
                        else
                        {
                            StringBuilder builder = new StringBuilder(charArray[i]);
                            builder.Replace(highestNumber.ToString(), "0");
                            charArray[i] = builder.ToString();
                        }
                    }
                }

                lineArray[i] = highestNumber;
                noHigehestNumberFound = true;
            }

            int count = 0;

            foreach (var item in lineArray)
            {
                count += item;
            }

            Console.WriteLine(count);
            Console.ReadKey();
        }

With a result of 1383 .

You can use this -

var rows = input.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim());
int sum = int.Parse(rows.First());
bool isFirstOdd = (sum & 1) == 1;
var path = from r in rows.Skip(1)
            let ints = r.Split(' ').Select(x => int.Parse(x)).ToArray()
            let isEvenElements = (ints.Length & 1) == 0
            let eligibleElements = ints.Where(x => (x & 1) == (isEvenElements && isFirstOdd ? 0 : 1))
            let b = eligibleElements.Max()
            select b;

sum += path.Sum();
Console.WriteLine(sum);

This solution is based on assumption that your series will continue as - 55 - 94 - 95 - 72 - 97 - 68...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM