给定一个正数n,求裂开的方法数

问题描述:

        给定一个正数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,求裂开的方法数。 动态规划优化状态依赖的技巧,注意裂开时后一种方法不能小于前一种。

代码:

代码一:暴力求解

    /**
     *
     * @param pre 要裂开的rest的前一个约束(rest裂开的第一个部分不能<pre)
     * @param rest 还剩下多少需要裂开
     * @return 裂开的方法数
     */
    public static int process(int pre,int rest){

        if (rest ==0){
            //之前裂开的方案,构成了1中有效方法
            return 1;
        }

        //如果rest还剩下东西
        if (pre >rest){
            return 0;
        }
        int ways = 0;
        for (int i =pre;i<=rest;i++){
            ways += process(i,rest-i);
        }
        return ways;
    }

代码二:暴力求解转化为动态规划

    public static int ways2(int n){
        if (n<1){
            return 0;
        }

        int[][] dp = new int[n+1][n+1];
        for (int pre = 1;pre<=n;pre++){
            dp[pre][0] = 1;
        }
        for (int pre = n;pre>=1;pre--){
            for (int rest = pre;rest<=n;rest++){
                int ways = 0;
                for (int i =pre;i<=rest;i++){
                    ways += dp[i][rest-i];
                }
                dp[pre][rest] = ways;
            }
        }
        return dp[1][n];
    }

代码三:对动态规划进行优化,消除枚举过程

    public static int ways3(int n){
        if (n<1){
            return 0;
        }
        int[][] dp = new int[n+1][n+1];
        for (int pre = 1;pre<dp.length;pre++){
            dp[pre][0] = 1;
        }
        for (int pre = 1;pre<dp.length;pre++){
            dp[pre][pre] = 1;
        }
        for (int pre = n-1;pre>0;pre--){
            for (int rest = pre+1;rest<=n;rest++){
                dp[pre][rest] = dp[pre+1][rest]+dp[pre][rest-pre];
            }
        }
        return dp[1][n];
    }

    public static void main(String[] args) {
        int n = 20;
        System.out.println(way1(n));
        System.out.println(ways2(n));
        System.out.println(ways3(n));
    }

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值