Problem 18
Maximum path sum I
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.
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:
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
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)
最大路径和 I
从下面展示的三角形的顶端出发,不断移动到在下一行与其相邻的元素,能够得到的最大路径和是23。
7 4
2 4 6
8 5 9 3
如上图,最大路径和为 3 + 7 + 4 + 9 = 23。
求从下面展示的三角形顶端出发到达底部,所能够得到的最大路径和:
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
注意: 在这个问题中,由于只有16384条路径,通过尝试所有的路径来解决问题是可行的。但是,对于第67题,虽然是一道相同类型的题目,但是三角形将拥有一百行,此时暴力破解将不能解决,而需要一个更加聪明的办法!;o)
package projecteuler;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class prj18 {
/**
* 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
* @throws IOException
*/
@Test
public void test() throws IOException {
List<int[]> dataList = Calculator.readData("E:\\whua\\zhsw\\cuppics\\src\\test\\java\\projecteuler\\Prj18_data.txt");
Calculator.calculate(dataList, 15);
}
public static class Calculator {
public enum Direction {
Down, DownLeft, DownRight
}
public static String directionStr( Direction dir){
if( dir.equals( Direction.Down)){
return "↓";
}else if ( dir.equals( Direction.DownLeft)){
return "↙";
}else if( dir.equals( Direction.DownRight)){
return "↘";
}
return "==";
}
public static List<int[]> readData(String path) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream(new File(path))));
String str = null;
List<int[]> ret = new ArrayList<int[]>();
while ((str = reader.readLine()) != null) {
String[] dataStr = str.split(" ");
int[] data = new int[dataStr.length];
for (int i = 0; i < dataStr.length; i++) {
data[i] = Integer.parseInt(dataStr[i]);
}
ret.add(data);
}
reader.close();
return ret;
}
public static void calculate(List<int[]> dataList, int lastDataLen) {
String[] traceStr = new String[lastDataLen];
String[] traceStrCopy = new String[lastDataLen];
int [] maxSumCopy = new int[ lastDataLen];
int [] maxSum = new int[ lastDataLen];
for (int i = 0; i < traceStr.length; i++) {
traceStr[i] = "";
traceStrCopy[i] = "";
maxSum[0] = dataList.get(0)[0];
}
for (int i = 1; i < dataList.size(); i++) {
int[] upData = dataList.get(i - 1);
int[] data = dataList.get(i);
copyArrays( maxSumCopy, maxSum );
for (int j = 0; j < data.length; j++) {
int id = calculateMaxSum(j, upData, data[j], maxSumCopy, maxSum);
markMax(j, id, traceStrCopy, traceStr);
}
traceStrCopy = copyStrs( traceStr);
}
for( int i = 0; i < lastDataLen; i ++){
System.out.println( traceStr[i]);
}
int maxId = 0;
int maxVal = 0;
for( int i = 0; i < lastDataLen; i ++){
if( maxSum[i] > maxVal){
maxVal = maxSum[i];
maxId = i;
}
}
System.out.println("maxId=" + maxId + ", val=" + maxVal);
}
private static String[] copyStrs( String[] traceStr) {
String []traceStrCopy = new String[ traceStr.length];
for( int i = 0; i < traceStr.length ; i ++){
traceStrCopy[i] = new String(traceStr[i]);
}
return traceStrCopy;
}
private static void copyArrays(int[] maxSumCopy, int[] maxSum) {
for( int i = 0 ; i < maxSum.length ; i ++){
maxSumCopy[i] = maxSum[i];
}
}
private static Direction markMax(int currentIndex, int upId, String[] traceStrCopy, String[] traceStr) {
Direction dir = null;
if (upId > currentIndex) {
dir = Direction.DownLeft;
} else if (upId == currentIndex) {
dir = Direction.Down;
} else {
dir = Direction.DownRight;
}
traceStr[currentIndex] = traceStrCopy[upId] + directionStr(dir);
return dir;
}
private static int calculateMaxSum(int jId, int[] upData, int val, int[] maxSumCopy, int [] maxSum) {
int maxVal = 0;
int maxId = 0;
for (int i = Math.max(0, jId - 1); i <= Math.min(jId,
upData.length + 1); i++) {
if (val + maxSumCopy[i] > maxVal) {
maxVal = val + maxSumCopy[i];
maxId = i;
}
}
maxSum[jId] = maxSumCopy[maxId] + val;
return maxId;
}
}
}