给定一个正数1,裂开的方法有一种,(1)
给定一个正数2,裂开的方法有两种,(1和1)、(2)
给定一个正数3,裂开的方法有三种,(1、1、1)、(1、2)、(3)
给定一个正数4,裂开的方法有五种,(1、1、1、1)、(1、1、2)、(1、3)、(2、2)、 (4)
给定一个正数n,求裂开的方法数。

import java.util.Scanner;

public class Main {
    public static int ways1(int n) {
        if (n < 1) {
            return 0;
        }
        return process(1, n);
    }

    public static int process(int pre, int rest) {
        if (rest == 0) {
            return 1;
        }
        if (pre > rest) {
            return 0;
        }
        int ways = 0;
        for (int i = pre; i <= rest; i++) {
            ways += process(i, rest - i);
        }
        return ways;
    }

    /**
     * 未使用优化的dp版本
     */
    private static int solveDp(int n) {
        int[][] dp = new int[n + 1][n + 1];
        for (int i = 1; i <= n; ++i) {
            dp[i][0] = 1;
        }
        for (int i = n; i >= 1; i--) {
            for (int j = i; j <= n; j++) {
                for (int k = i; k <= j; ++k) {
                    dp[i][j] += dp[k][j - k];
                }
            }
        }
        return dp[1][n];
    }

    /**
     * 优化后的dp
     * 斜率优化
     */
    private static int solveDpPlus(int n) {
        int[][] dp = new int[n + 1][n + 1];
        for (int i = 1; i <= n; ++i) {
            dp[i][0] = 1;
        }
        dp[n][n] = 1;
        for (int i = n - 1; i >= 1; i--) {
            for (int j = i; j <= n; j++) {
                // dp[i][j - i] + dp[i+1][j-i-1]+dp[i+2][j-i-2]+...+dp[j][0]
                dp[i][j] = dp[i + 1][j] + dp[i][j - i];
            }
        }
        return dp[1][n];
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int n = in.nextInt();
            int solve = solveDpPlus(n);
            int trueRet = ways1(n);
            if (solve != trueRet) {
                System.out.println("xxxxxx");
            }
            System.out.println(solve);
        }
    }
}
心之所向,素履以往 生如逆旅,一苇以航