project euler 18

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.

3
7 4
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

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。

3
7 4
4 6
8 5  9 3

如上图,最大路径和为 3 + 7 + 4 + 9 = 23。

求从下面展示的三角形顶端出发到达底部,所能够得到的最大路径和:

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

注意: 在这个问题中,由于只有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;
		}

	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值