POJ 1163 The Triangle 典型的递归问题

来源:互联网 发布:湖南第五届网络文化节 编辑:程序博客网 时间:2024/06/10 17:18

题意:寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或右下走。

解题思路:
二维数组存放数字三角形;
D[r][j]:第 r 行第 j 个数字(r,j 从 1 开始);
MaxSum(r,j):从 D(r,j)到底边的各条路径中,最佳路径的数字之和。
问题:求 MaxSum(1,1)。

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.io.StreamTokenizer;public class Main {    private static final int MAX = 101;    private static int D[][] = new int[MAX][MAX];    private static int maxSum[][] = new int[MAX][MAX];    private static int N;//  /**//   * 超时代码,因为有大量的重复计算。时间复杂度:2^n//   *///  private static int MaxSum(int i, int j) {//      if (i == N) {//          return D[i][j];//      }//      int x = MaxSum(i + 1, j);//      int y = MaxSum(i + 1, j + 1);//      return Math.max(x, y) + D[i][j];//  }    /**     * 记忆递归型动归程序,时间复杂度:n^2     * 每算出一个 MaxSum(r,j) 就保存起来,下次用到其值时,直接取用,则可以避免重复计算     */    private static int MaxSum(int i, int j) {        if (maxSum[i][j] != 0) {            return maxSum[i][j];        }        if (i == N) {            maxSum[i][j] = D[i][j];        } else {            int x = MaxSum(i + 1, j);            int y = MaxSum(i + 1, j + 1);            maxSum[i][j] = Math.max(x, y) + D[i][j];        }        return maxSum[i][j];    }    public static void main(String[] args) throws IOException {        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));        while (in.nextToken() != StreamTokenizer.TT_EOF) {            N = (int) in.nval;            for (int i = 1; i <= N; i++) {                for (int j = 1; j <= i; j++) {                    in.nextToken();                    D[i][j] = (int) in.nval;                }            }            out.println(MaxSum(1, 1));        }        out.flush();    }}

以下为优化方案:

优化:将递归转换为递推!!!
这里写图片描述

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.io.StreamTokenizer;public class Main {    private static final int MAX = 101;    private static int D[][] = new int[MAX][MAX];    private static int maxSum[][] = new int[MAX][MAX];    private static int N;    public static void main(String[] args) throws IOException {        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));        while (in.nextToken() != StreamTokenizer.TT_EOF) {            N = (int) in.nval;            for (int i = 1; i <= N; i++) {                for (int j = 1; j <= i; j++) {                    in.nextToken();                    D[i][j] = (int) in.nval;                }            }            System.arraycopy(D[N], 1, maxSum[N], 1, N);            for (int i = N - 1; i >= 1; i--) {                for (int j = 1; j <= i; j++) {                    maxSum[i][j] = Math.max(maxSum[i + 1][j], maxSum[i + 1][j + 1]) + D[i][j];                }            }            out.println(maxSum[1][1]);        }        out.flush();    }}

进一步优化:空间优化
没必要用二维 maxSum 数组存放每一个 MaxSum(r,j),只要从底层一行行向上递推,那么只要一堆数组 maxSum[100] 即可,即只要存储一行的 MaxSum 值就可以。

更进一步优化:空间优化
进一步考虑,连 maxSum 数组都可以不要,直接用 D 的第 n 行代替 maxSum 即可。节省空间,时间复杂度不变。

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.io.StreamTokenizer;public class Main {    private static final int MAX = 101;    private static int D[][] = new int[MAX][MAX];    private static int maxSum[];    private static int N;    public static void main(String[] args) throws IOException {        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));        while (in.nextToken() != StreamTokenizer.TT_EOF) {            N = (int) in.nval;            for (int i = 1; i <= N; i++) {                for (int j = 1; j <= i; j++) {                    in.nextToken();                    D[i][j] = (int) in.nval;                }            }            maxSum = D[N]; // maxSum 指向第 n 行            for (int i = N - 1; i >= 1; i--) {                for (int j = 1; j <= i; j++) {                    maxSum[j] = Math.max(maxSum[j], maxSum[j + 1]) + D[i][j];                }            }            out.println(maxSum[1]);        }        out.flush();    }}
原创粉丝点击