1 2 5组合100,有多少种方法

本文详细介绍了从穷举法到动态规划优化的过程,通过逐步减少循环次数来提高效率,最终得出最优解法。重点在于理解和应用动态规划的思想,剪枝不必要的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:用随意多个1 2 5三个数字的组合,使其值为100,有多少种组合方法?

基础解法:穷举法,1穷举100次,2穷举50次,5穷举20次,这种方法总共穷举的次数为100*50*20=100 000,性能太差,但是为了以后描述问题,先给出穷举法的代码:

for(int i = 0; i <= 100; i += 5){
     for(int j = 0; j <= 100; j += 2){
        for(int k = 0; k <= 100; k++)
            if(i + j + k == 100)
                count++;
     }
}

 进阶解法:通过对穷举法进行考察,在穷举的过程中j并不是每次都循环50次,而是随着i的增加循环次数不断减小,可以动态计算其循环次数为(100 - i) / 2,对于1的循环次数为可以动态计算为(100 - i - j),通过这个描述可以得到一个新的解法。

for(int i = 0; i <= 100; i += 5){
     for(int j = 0; j <= 100 - i; j += 2){
         for(int k = 0; k <= 100 - i - j; k++)
             if(i + j + k == 100)
                count++;
     }
}

 进一步优化:通过对上述算法的进一步分析,其实对1没有必要循环,只要i+j <= 100肯定存在一种解法,也就是说1肯定能补全差值。因此对1的循环是没有必要的。

for(int i = 0; i <= 100; i += 5){
     for(int j = 0; j <= 100 - i; j += 2){
         count++;
}

最优解法:通过对上述优化再进一步分析,对于2,是否有必要循环呢?其实我们只要知道100 - i对于2的倍数就行了,小于这个倍数100 - i - j可以用1来补全。因此可以有(100 - i) / 2种组合。考虑到i的个数可以为0,因此应该用这个倍数加1。因此我们只需要20次循环就可以找到总的倍数了。算法如下:

for(int i = 0; i <= 100; i += 5){
     count += (100 - i + 2) / 2; //其也可以写成count += ((100 - i) / 2 + 1)
}

其实通过这个小的编程题的一步步优化,我们已经在使用动态规划的思想了,其思想的核心就是剪去一些不必要的计算,在进阶解法中,我剪掉了不必要的循环次数,在进一步优化中我们剪掉了1的循环,最优解法中我们将对2的循环也剪掉了,形成了最好的解决办法。

### Java 实现计算1分、2分、5分硬币组成100元的所有组合方式 为了实现这个问题,可以采用三层嵌套的`for`循环结构来遍历所有可能的情况。每层循环分别代表不同面额硬币的数量变化范围。 #### 定义变量与初始化 首先设定三个整型变量用于记录三种硬币各自的数量,并设总金额目标为10000分(即100元),因为实际操作中更方便以分为单位进行计算[^1]。 ```java int oneCentCount; int twoCentsCount; int fiveCentsCount; final int targetAmountInCents = 100 * 100; // 将100元转换成分数表示 ``` #### 构建三重循环枚举可能性 通过调整每个面值对应的计数器,在合理范围内逐步增加其数值直到满足条件为止: - 对于1分钱来说,理论上可以从0到最大不超过剩余总额; - 同理对于2分和5分也遵循相同原则; 具体代码如下所示: ```java public class CoinCombination { public static void main(String[] args) { final int TARGET_AMOUNT_IN_CENTS = 100 * 100; // 转换成分 for (oneCentCount = 0; oneCentCount <= TARGET_AMOUNT_IN_CENTS / 1 ; oneCentCount++) { for(twoCentsCount=0;(twoCentsCount*2)<=TARGET_AMOUNT_IN_CENTS-oneCentCount*1;twoCentsCount++){ fiveCentsCount=(TARGET_AMOUNT_IN_CENTS-(oneCentCount*1)-(twoCentsCount*2))/5; if((oneCentCount*1)+(twoCentsCount*2)+(fiveCentsCount*5)==TARGET_AMOUNT_IN_CENTS){ System.out.println("方案:"+"1分×"+oneCentCount+", "+"2分×"+twoCentsCount+", "+"5分×"+fiveCentsCount); } } } } } ``` 这段程序会打印出每一个符合条件的解组合,其中包含了各个面额的具体数目[^2]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值