美文网首页
和果子一起来做题-Project Euler-18-R语言版本

和果子一起来做题-Project Euler-18-R语言版本

作者: 9d760c7ce737 | 来源:发表于2018-01-28 18:24 被阅读18次

    这是意义非凡的18题:

    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.

    2018-01-28_182813.png

    That is, 3 + 7 + 4 + 9 = 23.

    Find the maximum total from top to bottom of the triangle below:

    mark

    NOTE: As there are only 16384 routes, it is possible to solve this problem by trying every route. However, Problem 67, is the same challenge with a triangle containing one-hundred rows; it cannot be solved by brute force, and requires a clever method! ;o)

    这个问题就是很逗,他不准你用遍历的方法,说是有16384种,这个数字哪来的呢?因为每一次都是2个选择,总共要做14次选择

    2^14=16384

    即使用了遍历的方法,那么对于第67题,有100层,也就是2^99次方。

    只要是听过棋盘里面放谷子那个故事的人就知道2^64有多大。

    为了准确地知道2^99有多大,第67题给了个例子:

    假如我们1秒钟能够检测1万亿条路径,大概需要200亿年才能检测完。

    所以这题的算法比算力重要的多。

    我想了半天都没有想出什么结果,甚至我都不知道如何才能把那个三角形的数字给导入R语言,

    一开始我是这么弄的:

    
    a01 <- c(75)
    
    a02 <- c(95,64)
    
    a03 <- c(17,47,82)
    
    a04 <- c(18,35,87,10)
    
    a05 <- c(20,04,82,47,65)
    
    a06 <- c(19,01,23,75,03,34)
    
    a07 <- c(88,02,77,73,07,63,67)
    
    a08 <- c(99,65,04,28,06,16,70,92)
    
    a09 <- c(41,41,26,56,83,40,80,70,33)
    
    a10 <- c(41,48,72,33,47,32,37,16,94,29)
    
    a11 <- c(53,71,44,65,25,43,91,52,97,51,14)
    
    a12 <- c(70,11,33,28,77,73,17,78,39,68,17,57)
    
    a13 <- c(91,71,52,38,17,14,91,43,58,50,27,29,48)
    
    a14 <- c(63,66,04,68,89,53,67,30,73,16,69,87,40,31)
    
    a15 <- c(04,62,98,27,23,09,70,98,73,93,38,53,60,04,23)
    
    

    思前想后,还是搞不定,当时我想,这个要断更了。

    求助网络后,我发现一种奇特的解法。

    复制粘贴三角形数字保存为chart.txt

    read.table读入R语言并且转换成矩阵

    
    n <- 15
    
    chart <- read.table("chart.txt", sep = " ", fill = NA, col.names = 1:n)
    
    chart <- as.matrix(chart)
    
    

    查看一下chart是这个样子的:

    mark

    下面的思路特别精彩:

    第一个数是75,他向下可以到95,也可以到64

    那么第二行如果写成和的形式就是75+95=170,75+64=139

    对于第三行而言,有三个数,第一个数只能来自于上一行的第1个数,最后一个数只能是来源于上一行的最后一个数。

    变数实际上是第二个数,他可以有两个来源,他一从170过来,也可以从139过来,这里当然选择最大的170+47=217,

    所以前三行已经变成了这个样子:

    
    > chart
    
          X1  X2  X3  X4  X5  X6  X7  X8  X9  X10 X11 X12 X13 X14 X15
    
    [1,]  75  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
    
    [2,] 170 139  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
    
    [3,] 187 217 221  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
    
    

    顺着这个思路,每一行的头尾数都没有争议,有选择的是中间的每一个数,他们都有两个可能性,我们选取他们中的最大值。

    
    chart[2, 1:2] <- chart[2, 1:2] + chart[1, 1]
    
    for (i in 3:n) {
    
      chart[i, 1] <- chart[i, 1] + chart[(i - 1), 1]
    
      chart[i, i] <- chart[i, i] + chart[(i - 1), (i - 1)]
    
      for (j in 2:(i - 1)) {
    
        chart[i, j] <- chart[i, j] + max(chart[(i - 1), (j - 1):j])
    
      }
    
    }
    
    

    最终最大值可以在最后一行中找出:

    
    > result <- max(chart[n, ])
    
    > cat("The result is:", result, "\n")
    
    The result is: 1074
    
    

    好的,我们用这个方法去解答第67题:

    
    n <- 100
    
    chart <- read.table("chart.txt", sep = " ", fill = NA, col.names = 1:n)
    
    chart <- as.matrix(chart)
    
    chart[2, 1:2] <- chart[2, 1:2] + chart[1, 1]
    
    for (i in 3:n) {
    
      chart[i, 1] <- chart[i, 1] + chart[(i - 1), 1]
    
      chart[i, i] <- chart[i, i] + chart[(i - 1), (i - 1)]
    
      for (j in 2:(i - 1)) {
    
        chart[i, j] <- chart[i, j] + max(chart[(i - 1), (j - 1):j])
    
      }
    
    }
    
    

    答案几乎是秒出:

    
    > result <- max(chart[n, ])
    
    > cat("The result is:", result, "\n")
    
    The result is: 7273
    
    

    换种思路,让不可能变成可能,让200亿年缩成1s,甚至做完题我都有种荡气回肠的感觉。

    思维是我们超越时间的最强武器。

    相关文章

      网友评论

          本文标题:和果子一起来做题-Project Euler-18-R语言版本

          本文链接:https://www.haomeiwen.com/subject/zxezaxtx.html