简体   繁体   English

欧拉计划 18

[英]Project Euler 18

Hey, been working at Project Euler, and this one is giving me some problems嘿,一直在 Project Euler 工作,这个给我带来了一些问题

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.通过从下面三角形的顶部开始移动到下面一行的相邻数字,从上到下的最大总数是 23。

3 3

7 4 7 4

2 4 6 2 4 6

8 5 9 3 8 5 9 3

That is, 3 + 7 + 4 + 9 = 23.也就是说,3 + 7 + 4 + 9 = 23。

Find the maximum total from top to bottom of the triangle below:求下面三角形从上到下的最大总数:

... ...

NOTE: As there are only 16384 routes, it is possible to solve this problem by trying every route.注意:由于只有 16384 条路由,因此可以通过尝试每条路由来解决此问题。 However, Problem 67, is the same challenge with a triangle containing one-hundred rows;然而,问题 67 与包含一百行的三角形是相同的挑战; it cannot be solved by brute force, and requires a clever method!不是蛮力解决的,需要聪明的方法! ;o) ;o)

here's the algorithm I've used to solve it这是我用来解决它的算法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Problem18
{
    class Program
    {
        static void Main(string[] args)
        {
            string triangle = @"75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23";
            string[] rows = triangle.Split('\n');
            int currindex = 1;
            int total = int.Parse(rows[0]);
            Console.WriteLine(rows[0]);
            for (int i = 1; i < rows.Length; i++)
            {
                string[] array1 = rows[i].Split(' ');
                if (array1.Length > 1)
                {
                    if (int.Parse(array1[currindex - 1]) > int.Parse(array1[currindex]))
                    {
                        Console.WriteLine(array1[currindex - 1]);
                        total += int.Parse(array1[currindex - 1]);
                    }
                    else
                    {
                        Console.WriteLine(array1[currindex]);
                        total += int.Parse(array1[currindex]);
                        currindex++;
                    }
                }
            }
            Console.WriteLine("Total: " + total);
            Console.ReadKey();
        }
    }
}

now whenever i run it, it comes up with 1064, only 10 less then the solution -- 1074现在每当我运行它时,它都会出现 1064,仅比解决方案少 10-1074

i haven't found any problems with the algorithm and I did the problem by hand and also came up with 1064, anyone know if the solution is wrong, i'm interpreting the question wrong, or if there's just a flaw in the algorithm?我没有发现算法有任何问题,我手工解决了这个问题,还提出了 1064,有人知道解决方案是错误的,我对问题的解释是错误的,还是算法中存在缺陷?

Here is a graphical description:这是一个图形描述:

在此处输入图片说明

Here's what the bottom up method belisarius describes--using the trivial triangle given in problem 18--looks like, just in case the image in his post is confusing to anyone else.下面是belisarius 描述的自下而上的方法——使用问题18 中给出的平凡三角形——看起来像,以防万一他帖子中的图像对其他人造成混淆。

      03
    07  04
  02  04  06
08  05  09  03

      03
    07  04
  02  04  06
08  05  09  03
^^^^^^

      03
    07  04
  10  04  06
08  05  09  03
    ^^^^^^

      03
    07  04
  10  13  06
08  05  09  03
        ^^^^^^

      03
    07  04
  10  13  15
  ^^^^^^
08  05  09  03

      03
    20  04
  10  13  15
      ^^^^^^
08  05  09  03

      03
    20  04
  10  13  15
      ^^^^^^
08  05  09  03

      03
    20  19
    ^^^^^^
  10  13  15
08  05  09  03

      23
      ^^
    20  19
  10  13  15
08  05  09  03

Your problem is that your algorithm is a greedy algorithm, always finding local maxima.你的问题是你的算法是一个贪心算法,总是在寻找局部最大值。 Unfortunately that causes it to miss higher numbers down below because they are directly below lower numbers.不幸的是,这会导致它错过下面更高的数字,因为它们直接低于较低的数字。 For example, if the triangle were only 3 levels, your algorithm would pick 75 + 95 + 47 = 217, while the correct answer is 75 + 64 + 82 = 221.例如,如果三角形只有 3 个级别,您的算法将选择 75 + 95 + 47 = 217,而正确答案是 75 + 64 + 82 = 221。

The correct algorithm will either try every path and choose the one with the highest total, or compute paths from the bottom up (which allows you to avoid trying every one, thus being much faster).正确的算法将尝试每条路径并选择总数最高的路径,或者自下而上计算路径(这样可以避免尝试每条路径,从而更快)。 I should add that working from the bottom-up is not only much faster (O(n^2) instead of O(2^n)!), but also much easier to write (I did it in about 3 lines of code).我应该补充一点,自下而上的工作不仅要快得多(O(n^2) 而不是 O(2^n)!),而且编写起来也容易得多(我用大约 3 行代码完成了) .

You've written a greedy algorithm , which I don't think fits the requirements here.你写了一个贪心算法,我认为它不符合这里的要求。 Here's a quick example to demonstrate that point:这是一个简单的例子来证明这一点:

  1
 2 1
1 1 100 

Using your algorithm you'll reach a sum of 4, although the optimal solution is 102.使用您的算法,您将达到 4 的总和,尽管最佳解决方案是 102。

It is a good question based on dynamic programming .这是一个基于动态规划的好问题。 You need to create a 2d data structure(like vector in c++) then follow the bottom to up approach of dp.您需要创建一个二维数据结构(如 c++ 中的向量),然后按照 dp 的自下而上的方法。

The formula is dp[i][j] += max(dp[i + 1][j], dp[i + 1][j + 1]) .公式是dp[i][j] += max(dp[i + 1][j], dp[i + 1][j + 1]) Try coding on your own then if you are stuck at some point see my solution.尝试自己编码,然后如果您在某些时候遇到困难,请参阅我的解决方案。

vector< vector<int> > dp(n); // n is the number of rows
for (int i = 0 ; i < n; i++){
    for (int j = 0; j <= i; j++){
        cin >> val;
        dp[i].push_back(val);
    }
}
for (int i = n - 2 ; i >= 0; i--)
{
    for (int j = 0; j <= i; j++)
        dp[i][j] += max(dp[i + 1][j], dp[i + 1][j + 1]);    
}
cout << dp[0][0] << endl;   
return 0;
}

input: 3 2 4 5 6 8 9输入:3 2 4 5 6 8 9

output: 16输出:16

Recursive (not necessarily the best) approach:递归(不一定是最好的)方法:

    static int q18(){
        int matrix[][] = // BIG MATRIX;
        return getMaxPath(matrix, 0, 0, 0);
    }
    static int getMaxPath(int matrix[][], int sum, int row, int col){
        if(row==matrix.length) return sum;
        return Math.max(getMaxPath(matrix, sum+matrix[row][col], row+1, col),
                        getMaxPath(matrix, sum+matrix[row][col], row+1, col+1));
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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