18問目
下図の三角形に並べられた数字の一番上からスタートして, 1つ下の行の隣接する数字に移動していったとき, 通った数の合計の最大値は23.
つまり, . (訳注. 実は, というルートでも良い.)では, 次の三角形に並べられた数字の一番上から一番下までの合計の最大値を求めよ.
(図は省略.)メモ: 取り得るルートが16384 通りしかないので, この問題はしらみつぶしでも解ける. しかし, 問題67では, 100行ある三角形に対し同じ問題を解くことになる. これは力尽くでは解けず, 賢いやり方が求められる ;o)
http://projecteuler.net/index.php?section=problems&id=18
さて, まずはやはり数学的考察から.
この三角形のサイズを n としたときに, 力尽くの方法だと O(2^n) の計算量が必要だがこれは明かに二度手間の無駄がある. これは文字通り「トップダウン」で計算を行っているからで, 「ボトムアップ」で計算を行うと O(n^2) の計算量で済む. (やり方はシンプルなものなので, 詳細はソースコードを参照してください. )
それを実装したのが以下のソース. 計算機科学の分野のアルゴリズムでは良く使われる手ですね.
#include <stdio.h> #include <stdlib.h> #define SIZE 15 int triangle[][SIZE] = {{75}, {95, 64}, {17, 47, 82}, {18, 35, 87, 10}, {20, 4, 82, 47, 65}, {19, 1, 23, 75, 3, 34}, {88, 2, 77, 73, 7, 63, 67}, {99, 65, 4, 28, 6, 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, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31}, {4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23}}; int solveVer00(); int max(int, int); int main() { fprintf(stdout, "Solution: %d\n", solveVer00()); return EXIT_SUCCESS; } int solveVer00() { int row; int column; for (row = SIZE - 2; row >= 0; row--) { for (column = 0; column <= row; column++) { triangle[row][column] += max(triangle[row+1][column], triangle[row+1][column+1]); } } return triangle[0][0]; } int max(int num1, int num2) { return (num1 > num2 ? num1 : num2); }