1. 程式人生 > >演算法設計:整數劃分

演算法設計:整數劃分

// 將一個正整數n表示成一系列正整數之和,
// n = n1 + n2 + ... + nk ( 其中, n1 >= n2 >= ... >= nk , k >= 1 )
// 正整數n的一個這種表示稱為正整數n的一個劃分。
// 正整數n的不同的劃分個數稱為正整數n的劃分數。

// 求劃分數

// 將最大數n1不大於m的劃分個數記作q(n,m)。
// 遞迴關係如下:
// 1、q(n,1) = 1 , n >= 1;
// 2、q(n,m) = q(n,n) , m >= n;
// 3、q(n,n) = 1 + q(n,n-1);
// 4、q(n,m) = q(n,m-1) + q(n-m,m) , n > m > 1;

////////////////////////////////////////
#include "iostream.h"

int q( int n , int m )
{
 if( n < 1 || m < 1 )
  return 0;
 if( n == 1 || m == 1 )
  return 1;
 if( n < m )
  return q( n ,  n );
 if( n == m )
  return q( n , m - 1 ) + 1;
 return q( n , m - 1 ) + q( n - m , m );
}
void main()
{
 cout<<q(6,6)<<endl;
}

////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////

// 求劃分
//
#include "iostream.h"
#include "iomanip.h"

#define max 1024

void print( int *map , int len )
{
 static int total = 1;
 cout<<"劃分"<<setw(4)<<total++<<" : ";
 for( int i = 0 ; i < len ; i++ )
  cout<<setw(5)<<map[i];
 cout<<endl;
}

int p( int n , int m , int *map , int len )
{
 if( n >= 1 && m == 1 )
 {
 // flag1:
 // 當 m=1 時,只有一種分法,n = 1 + 1 + ...
 // 與 flag2 合作,可以完成這種分解的輸出
  map[len] = 1;
  p( n - 1 , m , map , len+1 );
  return 1;
 }
 else if( n == 0 && m == 1 )
 {
 // flag2:
 // 配合 flag1 ,完成對 m=1 劃分的處理
  print( map , len );
  return 1;
 }
 else if( n == 1 && m > 1 )
 {
 // flag3:
 // 當 n=1 時,分解已經完成,進行輸出處理
  map[len] = n;
  print( map , len + 1 );
  return 1;
 }
 else if( n < m )
 {
 // flag4:
 // 由於所處位置的關係,此時及以下情況中的 m , n 都 > 1
  return p( n , n , map , len );
 }
 else if( n == m )
 {
 // flag5:
 // 這種情況下,map 位賦為 m,則可完成一種劃分
  map[len] = m;
  print( map , len + 1 );
 // 繼續下種情況的處理
  return p( n , m - 1 , map , len ) + 1;
 }
 else
 {
 // 有兩種處理方法
 // 方法一:
 // 當前 map 位賦為 m , 處理 p( n-m , m )
  map[len] = m;
  int s1 = p( n - m , m , map , len + 1 );
 // 方法二:
  int s2 = p( n , m - 1 , map , len );
  return s1 + s2;
 }

}
void main()
{
 int map[max] = { 0 };
 int len = 0;

 cout<<"total="<<p( 6 , 6 , map , len )<<endl;
}
// 程式2是程式1的擴充,基本思想與程式1相似,在理解程式1的基礎上,
// 可以很好得理解程式2

////////////////////////////////////////
// 參考文獻:
// 計算機演算法設計與分析 電子工業出版社