隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0

          導航

          <2008年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          公告

          關(guān)注我的新浪微博

          我的著作









          常用鏈接

          留言簿(126)

          我參與的團隊

          隨筆分類(818)

          隨筆檔案(310)

          文章分類(1)

          文章檔案(8)

          相冊

          ADSL、3G查詢

          CSDN

          eclipse

          ibm

          Java EE

          Linux

          Web

          云服務

          代理網(wǎng)站

          關(guān)注的網(wǎng)站

          協(xié)議

          喜歡的Blog

          國內(nèi)廣告平臺

          圖書出版

          在線培訓

          開發(fā)工具

          微博客戶端

          手機鈴聲

          操作系統(tǒng)

          • ReactOS
          • 一個與windowXP/2003兼容的操作系統(tǒng)

          數(shù)學

          文件格式

          源碼資源

          移動(Mobile)

          編程語言

          英語學習

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1972347
          • 排名 - 6

          最新評論

          閱讀排行榜

          評論排行榜

          整數(shù)劃分算法原理與實現(xiàn)

          本文為原創(chuàng),如需轉(zhuǎn)載,請注明作者和出處,謝謝!

              整數(shù)劃分問題是將一個正整數(shù)n拆成一組數(shù)連加并等于n的形式,且這組數(shù)中的最大加數(shù)不大于n。
              如6的整數(shù)劃分為
             
              6
              5 + 1
              4 + 2, 4 + 1 + 1
              3 + 3, 3 + 2 + 1, 3 + 1 + 1 + 1
              2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 + 1 + 1 + 1
              1 + 1 + 1 + 1 + 1 + 1
             
              共11種。下面介紹一種通過遞歸方法得到一個正整數(shù)的劃分數(shù)。
             
              遞歸函數(shù)的聲明為 int split(int n, int m);其中n為要劃分的正整數(shù),m是劃分中的最大加數(shù)(當m > n時,最大加數(shù)為n),
              1 當n = 1或m = 1時,split的值為1,可根據(jù)上例看出,只有一個劃分1 或 1 + 1 + 1 + 1 + 1 + 1
              可用程序表示為if(n == 1 || m == 1) return 1;
             
              2 下面看一看m 和 n的關(guān)系。它們有三種關(guān)系
              (1) m > n
              在整數(shù)劃分中實際上最大加數(shù)不能大于n,因此在這種情況可以等價為split(n, n);
              可用程序表示為if(m > n) return split(n, n);   
              (2) m = n
              這種情況可用遞歸表示為split(n, m - 1) + 1,從以上例子中可以看出,就是最大加
              數(shù)為6和小于6的劃分之和
              用程序表示為if(m == n) return (split(n, m - 1) + 1);
              (3) m < n
              這是最一般的情況,在劃分的大多數(shù)時都是這種情況。
              從上例可以看出,設(shè)m = 4,那split(6, 4)的值是最大加數(shù)小于4劃分數(shù)和整數(shù)2的劃分數(shù)的和。
              因此,split(n, m)可表示為split(n, m - 1) + split(n - m, m)
             
              根據(jù)以上描述,可得源程序如下:
            
          #include <stdio.h>

             
          int split(int n, int m)
             {
                
          if(n < 1 || m < 1return 0;
                
          if(n == 1 || m == 1return 1;
                
          if(n < m) return split(n, n);
                
          if(n == m) return (split(n, m - 1+ 1);
                
          if(n > m) return (split(n, m - 1+ split((n - m), m));
            }

          int main()
          {
               printf(
          "12的劃分數(shù): %d", split(1212));
              
          return 0;
          }

          將正整數(shù)劃分成連續(xù)的正整數(shù)之和
          如15可以劃分成4種連續(xù)整數(shù)相加的形式:
          15
          7 8
          4 5 6
          1 2 3 4 5

              首先考慮一般的形式,設(shè)n為被劃分的正整數(shù),x為劃分后最小的整數(shù),如果n有一種劃分,那么
          結(jié)果就是x,如果有兩種劃分,就是x和x x + 1, 如果有m種劃分,就是 x 、x x + 1 、 x x + 1 x + 2 、... 、x x + 1 x + 2 ... x + m - 1
          將每一個結(jié)果相加得到一個公式(i * x + i * (i - 1) / 2) = n,i為當前劃分后相加的正整數(shù)個數(shù)。
          滿足條件的劃分就是使x為正整數(shù)的所有情況。
          如上例,當i = 1時,即劃分成一個正整數(shù)時,x = 15, 當i = 2時, x = 7。
          當x = 3時,x = 4, 當x = 4時,4/9,不是正整數(shù),因此,15不可能劃分成4個正整數(shù)相加。
          當x = 5時,x = 1。

              這里還有一個問題,這個i的最大值是多少?不過有一點可以肯定,它一定比n小。我們可以做一個假設(shè),
          假設(shè)n可以拆成最小值為1的劃分,如上例中的1 2 3 4 5。這是n的最大數(shù)目的劃分。如果不滿足這個假設(shè),
          那么 i 一定比這個劃分中的正整數(shù)個數(shù)小。因此可以得到這樣一個公式i * (i + 1) / 2 <= n,即當i滿足
          這個公式時n才可能被劃分。

          綜合上述,源程序如下
          int split1(int n)
          {
              
          int i, j, m = 0, x, t1, t2;
             
          // 在這里i + 1之所以變?yōu)閕 - 1,是因為i * (i - 1) / 2這個式子在下面多次用到,
            
          // 為了避免重復計算,因此將這個值計算完后保存在t1中。并且將<= 號變?yōu)榱?lt;號。
              for(i = 1; (t1 = i * (i - 1/ 2< n; i++
              {
                  t2 
          = (n - t1);
                  x 
          =  t2 / i;
                  
          if(x <= 0break;
                  
          if((n - t1) % i == 0)
                  {
                      printf(
          "%d ", x);
                      
          for(j = 1; j < i; j++)
                          printf(
          "%d ", x + j);
                      printf(
          "\n");
                      m
          ++;
                  }
              }
              
          return m;
          }




          Android開發(fā)完全講義(第2版)(本書版權(quán)已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2008-05-11 15:41 銀河使者 閱讀(2035) 評論(0)  編輯  收藏 所屬分類: algorithmC/C++ 原創(chuàng)

          主站蜘蛛池模板: 大连市| 济阳县| 泗水县| 黄陵县| 教育| 久治县| 霍山县| 合阳县| 龙胜| 南汇区| 丹江口市| 林西县| 郸城县| 扶绥县| 通江县| 兰州市| 区。| 格尔木市| 高雄县| 固阳县| 外汇| 永宁县| 古蔺县| 宜宾市| 永城市| 漳浦县| 神池县| 蒲城县| 南丰县| 阿克陶县| 北流市| 扶余县| 万宁市| 东乌珠穆沁旗| 饶阳县| 通海县| 和平区| 启东市| 桂林市| 大竹县| 沙湾县|