剪绳子

题目描述

给定一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]* k[1] * … *k[m]可能的最大乘积是多少?例如长度为8的绳子,可以剪成2,3,3段,最大乘积为18。
此题提供动态规划和贪心算法两种解法:

动态规划

假设f(n)为长度为n的绳子剑成若干段后的最大乘积。那么如果我们只剪一刀,该绳子就会分为两部分,假设在i上剪断,我们再求出这两部分绳子的最大乘积f(i),f(n-i)。然后不断以相同的方式进行分割,可以得到f(n)=max(f(i)*f(n-i))。
我们可以用递归求出来,因为这是一个自上而下的式子,但递归有许多重复的计算,效率低。这题我们采用自下而上的方式,用动态规划来做。f(1),f(2),f(3)都很容易得到,然后我们可以推出f(4),f(5),然后一直往后推出至f(n)。

public int cutting(int length) {
		//考虑到至少要剪两刀(m>1),先将剪后的f(n)<n的情况作为特例排除
	    if(length<2)
	    	return 0;
	    if(length==2)
	    	return 1;
	    if(length==3)
	    	return 2;
	    int max=0;//存储当前最大的f(n)
	    int[] array = new int[length+1];//array[n] = f[n]
	    array[0]=0;
	    array[1]=1;
	    array[2]=2;
	    array[3]=3;
	    for(int i=4;i<=length;i++) {
	    	for(int f=1;f<=i/2;f++) {//绳子只需要剪前一半的就可以,剪i和剪n-i是一回事
	    		int pro = array[f]*array[i-f];
	    		if(pro>max)
	    			max=pro;
	    		array[i]=max;
	    	}
	    }
	    return array[length];
	}

贪心算法

当n<=3时,不再进行剪切,因为会比n小。
当n==4时,将n=2*2,因为只有两种剪法,剪成1,3比较小。
当n>=5时,我们要把所有的绳子都剪成2或者3,同时我们要尽可能的多剪长度为3的绳子,因为3(n-3)>=2(n-2),当剩余的小于5时就没有必要再剪。

public int cutting1(int length) {
		if(length<2)
			return 0;
		if(length==2)
			return 1;
		if(length==3)
			return 2;
		if(length==4)
			return 4;
		int max=1;
		while(length>=5) {
			length-=3;
			max*=3;
		}
		if(length!=0)
			max*=length;
		return max;
	}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值