经典算法:整数划分问题

整数划分问题(算法分析与设计 P12):将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。正整数n的这种表示称为正整数n的划分。求正整数n的不同划分个数和方案。例如正整数6有如下11种不同的划分:

 
 
  1. 6
  2. 5+1
  3. 4+2, 4+1+1
  4. 3+3, 3+2+1, 3+1+1+1
  5. 2+2+2, 2+2+1+1, 2+1+1+1+1
  6. 1+1+1+1+1+1

由于将思路写作注释更方便理解,就不再在前面赘述了,给出代码及思路如下:

 
 
  1. #include
  2. int list[255];
  3. // num: 要分割的原始数字, n: 当前要分割的数字, k: 已经分割出的数量, sum: 已分割出的数字之和
  4. void split(int num, int n = 0, int k = 0, int sum = 0){
  5.         // 如果当前要分割的数字未传入,则当前分割的数字即为要分割的原始数字,减少传入参数数量
  6.         if(== 0){
  7.                 n =  num;
  8.         }
  9.         // 如果已分割的数字之和等于要分割的原始数字,即分割完毕
  10.         if(sum + n == num){
  11.                 // 将最后一个数字存入数组
  12.                 list[k] = n;
  13.                 // 判断已分割的数字是否后面小于前面,防止重复
  14.                 bool flag = true;
  15.                 // 暂时未想到更好办法去除重复项,每次都要遍历数组,性能较低
  16.                 for(int i = 1; i <= k; ++i){
  17.                         if(list[i] > list[- 1]){
  18.                                 flag = false;
  19.                         }
  20.                 }
  21.                 // 如果数组合法,则输出
  22.                 if(flag){
  23.                         printf("%d", list[0]);
  24.                         for(int i = 1; i <= k; ++i){
  25.                                 printf("+%d", list[i]);
  26.                         }
  27.                         printf("\n");
  28.                 }
  29.         }
  30.         // 从小到大进行分割
  31.         for(int i = 1; i < n; ++i){
  32.                 // 分割剩下的数字存入数组
  33.                 list[k] = n - i;
  34.                 // 分割出的数字继续分割
  35.                 split(num, i, k + 1, sum + n - i);
  36.         }
  37. }
  38. int main(){
  39.         int n;
  40.         while(~scanf("%d", &n)){
  41.                 split(n);
  42.         }
  43.         return 0;
  44. }



=======================签 名 档=======================

原文地址(我的博客):http://www.clanfei.com/2012/12/1672.html
欢迎访问交流,至于我为什么要多弄一个博客,因为我热爱前端,热爱网页,我更希望有一个更加自由、真正属于我自己的小站,或许并不是那么有名气,但至少能够让我为了它而加倍努力。。
=======================签 名 档=======================





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值