• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
james1207

博客园    首页    新随笔    联系   管理    订阅  订阅

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

问题描述:用随意多个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的循环也剪掉了,形成了最好的解决办法。

posted @ 2013-10-12 23:10  Class Xman  阅读(1186)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3