天天看點

Project euler 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.

3

7 4

2 4 6

8 5 9 3

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

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

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

    最簡單的方法就是窮舉,從根節點出發,每個節點都有兩個分叉,到達底部的路徑有估計有2的指數級的數目(有會算的朋友請留言,我的組合數學都還給老師了),不過這道題顯然是符合動态規劃的特征,往下遞增一層的某個節點的最佳結果f[i][j]肯定是上一層兩個入口節點對應的最佳結果的最大值,也就是f[i-1][j]或者f[i-1][j+1],遞歸的邊界就是定點f[0][0]=75。是以我的解答如下,考慮了金字塔邊界的情況,資料按照金字塔型存儲在numbers.txt中,

import java.io.bufferedreader;

import java.io.inputstreamreader;

public class euler18problem {

    public static void maxsun(int[][] a, int rows, int cols) {

        // 結果清單

        int[][] f = new int[15][15];

        // 路徑,用于輸出計算路徑

        int[][] path = new int[15][15];

        // 遞歸邊界

        f[0][0] = a[0][0];

        path[0][0] = 0;

        // 遞推

        for (int i = 1; i < rows; i++) {

            int col = i + 1;

            // 決策

            for (int j = 0; j < col; j++) {

                // 左邊界

                if (j - 1 < 0) {

                    f[i][j] = f[i - 1][j] + a[i][j];

                    path[i][j] = j;

                } else if (j + 1 > col) { // 右邊界

                    f[i][j] = f[i - 1][j - 1] + a[i][j];

                    path[i][j] = j - 1;

                } else {

                    // 處于中間位置

                    if (f[i - 1][j] <= f[i - 1][j - 1]) {

                        f[i][j] = f[i - 1][j - 1] + a[i][j];

                        path[i][j] = j - 1;

                    } else {

                        f[i][j] = f[i - 1][j] + a[i][j];

                        path[i][j] = j;

                    }

                }

            }

        }

        // 求出結果

        int result = 0, col = 0;

        for (int i = 0; i < cols; i++) {

            if (f[14][i] > result) {

                result = f[14][i];

                col = i;

        // 輸出路徑

        system.out.println("row=14,col=" + col + ",value=" + a[14][col]);

        for (int i = rows - 2; i >= 0; i--) {

            col = path[i][col];

            system.out.println("row=" + i + ",col=" + col + ",value="

                    + a[i][col]);

        system.out.println(result);

    }

    public static void main(string[] args) throws exception {

        int rows = 15;

        int cols = 15;

        int[][] a = new int[rows][cols];

        bufferedreader reader = new bufferedreader(new inputstreamreader(

                euler18problem.class.getresourceasstream("/numbers.txt")));

        string line = null;

        int row = 0;

        while ((line = reader.readline()) != null && !line.trim().equals("")) {

            string[] numbers = line.split(" ");

            for (int i = 0; i < numbers.length; i++) {

                a[row][i] = integer.parseint(numbers[i]);

            row++;

        reader.close();

        maxsun(a, rows, cols);

}

     執行結果如下,包括了路徑輸出:

row=14,col=9,value=93

row=13,col=8,value=73

row=12,col=7,value=43

row=11,col=6,value=17

row=10,col=5,value=43

row=9,col=4,value=47

row=8,col=3,value=56

row=7,col=3,value=28

row=6,col=3,value=73

row=5,col=2,value=23

row=4,col=2,value=82

row=3,col=2,value=87

row=2,col=1,value=47

row=1,col=0,value=95

row=0,col=0,value=75

1074

    ps.并非我閑的蛋疼在半夜做題,隻是被我兒子折騰的無法睡覺了,崩潰。

文章轉自莊周夢蝶  ,原文釋出時間2009-09-27

繼續閱讀