整數劃分的非遞迴演算法(C語言)
記錄點滴成長:
整數劃分的非遞迴演算法
例如將整數6劃分為如下:
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
如6有11個劃分。
#include "stdio.h"
void Divinteger(int n)
{
if (n==1) //處理輸入值為1的情況,因為如果輸入1,就不用再劃分
{
printf("只有一種劃分:1/n");
return;
}
if (n == 2) //處理輸入值為2 的情況,如果輸入為2,只要寫成1+1就可以了。
{
printf("第1種劃分:2/n");
printf("第2種劃分:1 1/n");
printf("一共有2種劃分!/n");
return;
}
int *a =new int(n); //定義動態陣列,因為當n大於2時,如3=2+1,這時就需要對2進行相似劃分,其大小是不固定的,因而用動態陣列。
int div=0; //每一行劃分的陣列下標
int k=1;//記錄種類的值。
a[0] = n - 1;
a[1] = 1;
div = 2; //第二次一定劃分為2個值。n-1和1
printf("第%2d種劃分:%d /n",1,n);
int i;
do{
k++;
printf("第%2d種劃分:",k);
printf("%d", a[0]);
for (i = 1; i < div; i++)
printf(" %d", a[i]);
printf("/n");
int s = 0;
do{
s += a[--div];
}while (div >= 0 && a[div] == 1); //這裡用來找到非1的可以繼續劃分的值,如5 1,通過這一部找到5;
if (div == -1)
break;
int d = a[div] - 1; //判斷是否還有數字可以繼續劃分。
if (d == 1) //這句戶用來為下一個迴圈做準備,
{
while (s > 0) //s存放著下一行一共有幾個值
{
a[div++] = 1; //將下一行的值全部賦值為1.等待下一個迴圈輸出。
s--;
}
}
else //表示還有值可以繼續劃分
{
do{
a[div++] = d;// 相當於向右移動一位,進入下一次劃分(對4)
s -= d;
}while (s >= d); //得出a[0]=4
if (s != 0)
a[div++] = s; //得出a[1]=2 div=2
}
}while (1);
printf("/n一共有 %d 種方法!/n/n",k);
}
void main()
{
int n;
printf("輸入你要求的劃分整數值:/n");//輸入n值
scanf("%d", &n);
Divinteger(n); //呼叫劃分函式
}